diff options
Diffstat (limited to 'core')
318 files changed, 17211 insertions, 12651 deletions
diff --git a/core/SCsub b/core/SCsub index 59fe63b4b3..c9f84a9a00 100644 --- a/core/SCsub +++ b/core/SCsub @@ -3,7 +3,6 @@ Import("env") import core_builders -import make_binders env.core_sources = [] @@ -26,7 +25,7 @@ if "SCRIPT_AES256_ENCRYPTION_KEY" in os.environ: txts = "0x" + e[i * 2 : i * 2 + 2] try: int(txts, 16) - except: + except Exception: ec_valid = False txt += txts if not ec_valid: @@ -35,10 +34,13 @@ if "SCRIPT_AES256_ENCRYPTION_KEY" in os.environ: # NOTE: It is safe to generate this file here, since this is still executed serially with open("script_encryption_key.gen.cpp", "w") as f: - f.write('#include "core/project_settings.h"\nuint8_t script_encryption_key[32]={' + txt + "};\n") + f.write('#include "core/config/project_settings.h"\nuint8_t script_encryption_key[32]={' + txt + "};\n") # Add required thirdparty code. + +thirdparty_obj = [] + env_thirdparty = env.Clone() env_thirdparty.disable_warnings() @@ -56,7 +58,7 @@ thirdparty_misc_sources = [ "clipper.cpp", ] thirdparty_misc_sources = [thirdparty_misc_dir + file for file in thirdparty_misc_sources] -env_thirdparty.add_source_files(env.core_sources, thirdparty_misc_sources) +env_thirdparty.add_source_files(thirdparty_obj, thirdparty_misc_sources) # Zlib library, can be unbundled if env["builtin_zlib"]: @@ -82,18 +84,14 @@ if env["builtin_zlib"]: if env["target"] == "debug": env_thirdparty.Append(CPPDEFINES=["ZLIB_DEBUG"]) - env_thirdparty.add_source_files(env.core_sources, thirdparty_zlib_sources) + env_thirdparty.add_source_files(thirdparty_obj, thirdparty_zlib_sources) # Minizip library, could be unbundled in theory # However, our version has some custom modifications, so it won't compile with the system one thirdparty_minizip_dir = "#thirdparty/minizip/" -thirdparty_minizip_sources = [ - "ioapi.c", - "unzip.c", - "zip.c", -] +thirdparty_minizip_sources = ["ioapi.c", "unzip.c", "zip.c"] thirdparty_minizip_sources = [thirdparty_minizip_dir + file for file in thirdparty_minizip_sources] -env_thirdparty.add_source_files(env.core_sources, thirdparty_minizip_sources) +env_thirdparty.add_source_files(thirdparty_obj, thirdparty_minizip_sources) # Zstd library, can be unbundled in theory # though we currently use some private symbols @@ -135,10 +133,14 @@ if env["builtin_zstd"]: # Also needed in main env includes will trigger warnings env.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"]) - env_thirdparty.add_source_files(env.core_sources, thirdparty_zstd_sources) + env_thirdparty.add_source_files(thirdparty_obj, thirdparty_zstd_sources) + + +env.core_sources += thirdparty_obj -# Godot's own sources +# Godot source files + env.add_source_files(env.core_sources, "*.cpp") # Certificates @@ -152,27 +154,16 @@ env.CommandNoCache( env.Run(core_builders.make_certs_header, "Building ca-certificates header."), ) -# Make binders -env.CommandNoCache( - ["method_bind.gen.inc", "method_bind_ext.gen.inc", "method_bind_free_func.gen.inc"], - "make_binders.py", - env.Run(make_binders.run, "Generating method binders."), -) - # Authors env.Depends("#core/authors.gen.h", "../AUTHORS.md") env.CommandNoCache( - "#core/authors.gen.h", - "../AUTHORS.md", - env.Run(core_builders.make_authors_header, "Generating authors header."), + "#core/authors.gen.h", "../AUTHORS.md", env.Run(core_builders.make_authors_header, "Generating authors header.") ) # Donors env.Depends("#core/donors.gen.h", "../DONORS.md") env.CommandNoCache( - "#core/donors.gen.h", - "../DONORS.md", - env.Run(core_builders.make_donors_header, "Generating donors header."), + "#core/donors.gen.h", "../DONORS.md", env.Run(core_builders.make_donors_header, "Generating donors header.") ) # License @@ -190,9 +181,17 @@ SConscript("crypto/SCsub") SConscript("io/SCsub") SConscript("debugger/SCsub") SConscript("input/SCsub") -SConscript("bind/SCsub") +SConscript("variant/SCsub") +SConscript("object/SCsub") +SConscript("templates/SCsub") +SConscript("string/SCsub") +SConscript("config/SCsub") +SConscript("error/SCsub") # Build it all as a library lib = env.add_library("core", env.core_sources) env.Prepend(LIBS=[lib]) + +# Needed to force rebuilding the core files when the thirdparty code is updated. +env.Depends(lib, thirdparty_obj) diff --git a/core/bind/SCsub b/core/bind/SCsub deleted file mode 100644 index 19a6549225..0000000000 --- a/core/bind/SCsub +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python - -Import("env") - -env.add_source_files(env.core_sources, "*.cpp") diff --git a/core/color_names.inc b/core/color_names.inc deleted file mode 100644 index 2b50d88b02..0000000000 --- a/core/color_names.inc +++ /dev/null @@ -1,155 +0,0 @@ -// Names from https://en.wikipedia.org/wiki/X11_color_names -#include "core/map.h" - -static Map<String, Color> _named_colors; -static void _populate_named_colors() { - if (!_named_colors.empty()) { - return; - } - _named_colors.insert("aliceblue", Color(0.94, 0.97, 1.00)); - _named_colors.insert("antiquewhite", Color(0.98, 0.92, 0.84)); - _named_colors.insert("aqua", Color(0.00, 1.00, 1.00)); - _named_colors.insert("aquamarine", Color(0.50, 1.00, 0.83)); - _named_colors.insert("azure", Color(0.94, 1.00, 1.00)); - _named_colors.insert("beige", Color(0.96, 0.96, 0.86)); - _named_colors.insert("bisque", Color(1.00, 0.89, 0.77)); - _named_colors.insert("black", Color(0.00, 0.00, 0.00)); - _named_colors.insert("blanchedalmond", Color(1.00, 0.92, 0.80)); - _named_colors.insert("blue", Color(0.00, 0.00, 1.00)); - _named_colors.insert("blueviolet", Color(0.54, 0.17, 0.89)); - _named_colors.insert("brown", Color(0.65, 0.16, 0.16)); - _named_colors.insert("burlywood", Color(0.87, 0.72, 0.53)); - _named_colors.insert("cadetblue", Color(0.37, 0.62, 0.63)); - _named_colors.insert("chartreuse", Color(0.50, 1.00, 0.00)); - _named_colors.insert("chocolate", Color(0.82, 0.41, 0.12)); - _named_colors.insert("coral", Color(1.00, 0.50, 0.31)); - _named_colors.insert("cornflower", Color(0.39, 0.58, 0.93)); - _named_colors.insert("cornsilk", Color(1.00, 0.97, 0.86)); - _named_colors.insert("crimson", Color(0.86, 0.08, 0.24)); - _named_colors.insert("cyan", Color(0.00, 1.00, 1.00)); - _named_colors.insert("darkblue", Color(0.00, 0.00, 0.55)); - _named_colors.insert("darkcyan", Color(0.00, 0.55, 0.55)); - _named_colors.insert("darkgoldenrod", Color(0.72, 0.53, 0.04)); - _named_colors.insert("darkgray", Color(0.66, 0.66, 0.66)); - _named_colors.insert("darkgreen", Color(0.00, 0.39, 0.00)); - _named_colors.insert("darkkhaki", Color(0.74, 0.72, 0.42)); - _named_colors.insert("darkmagenta", Color(0.55, 0.00, 0.55)); - _named_colors.insert("darkolivegreen", Color(0.33, 0.42, 0.18)); - _named_colors.insert("darkorange", Color(1.00, 0.55, 0.00)); - _named_colors.insert("darkorchid", Color(0.60, 0.20, 0.80)); - _named_colors.insert("darkred", Color(0.55, 0.00, 0.00)); - _named_colors.insert("darksalmon", Color(0.91, 0.59, 0.48)); - _named_colors.insert("darkseagreen", Color(0.56, 0.74, 0.56)); - _named_colors.insert("darkslateblue", Color(0.28, 0.24, 0.55)); - _named_colors.insert("darkslategray", Color(0.18, 0.31, 0.31)); - _named_colors.insert("darkturquoise", Color(0.00, 0.81, 0.82)); - _named_colors.insert("darkviolet", Color(0.58, 0.00, 0.83)); - _named_colors.insert("deeppink", Color(1.00, 0.08, 0.58)); - _named_colors.insert("deepskyblue", Color(0.00, 0.75, 1.00)); - _named_colors.insert("dimgray", Color(0.41, 0.41, 0.41)); - _named_colors.insert("dodgerblue", Color(0.12, 0.56, 1.00)); - _named_colors.insert("firebrick", Color(0.70, 0.13, 0.13)); - _named_colors.insert("floralwhite", Color(1.00, 0.98, 0.94)); - _named_colors.insert("forestgreen", Color(0.13, 0.55, 0.13)); - _named_colors.insert("fuchsia", Color(1.00, 0.00, 1.00)); - _named_colors.insert("gainsboro", Color(0.86, 0.86, 0.86)); - _named_colors.insert("ghostwhite", Color(0.97, 0.97, 1.00)); - _named_colors.insert("gold", Color(1.00, 0.84, 0.00)); - _named_colors.insert("goldenrod", Color(0.85, 0.65, 0.13)); - _named_colors.insert("gray", Color(0.75, 0.75, 0.75)); - _named_colors.insert("webgray", Color(0.50, 0.50, 0.50)); - _named_colors.insert("green", Color(0.00, 1.00, 0.00)); - _named_colors.insert("webgreen", Color(0.00, 0.50, 0.00)); - _named_colors.insert("greenyellow", Color(0.68, 1.00, 0.18)); - _named_colors.insert("honeydew", Color(0.94, 1.00, 0.94)); - _named_colors.insert("hotpink", Color(1.00, 0.41, 0.71)); - _named_colors.insert("indianred", Color(0.80, 0.36, 0.36)); - _named_colors.insert("indigo", Color(0.29, 0.00, 0.51)); - _named_colors.insert("ivory", Color(1.00, 1.00, 0.94)); - _named_colors.insert("khaki", Color(0.94, 0.90, 0.55)); - _named_colors.insert("lavender", Color(0.90, 0.90, 0.98)); - _named_colors.insert("lavenderblush", Color(1.00, 0.94, 0.96)); - _named_colors.insert("lawngreen", Color(0.49, 0.99, 0.00)); - _named_colors.insert("lemonchiffon", Color(1.00, 0.98, 0.80)); - _named_colors.insert("lightblue", Color(0.68, 0.85, 0.90)); - _named_colors.insert("lightcoral", Color(0.94, 0.50, 0.50)); - _named_colors.insert("lightcyan", Color(0.88, 1.00, 1.00)); - _named_colors.insert("lightgoldenrod", Color(0.98, 0.98, 0.82)); - _named_colors.insert("lightgray", Color(0.83, 0.83, 0.83)); - _named_colors.insert("lightgreen", Color(0.56, 0.93, 0.56)); - _named_colors.insert("lightpink", Color(1.00, 0.71, 0.76)); - _named_colors.insert("lightsalmon", Color(1.00, 0.63, 0.48)); - _named_colors.insert("lightseagreen", Color(0.13, 0.70, 0.67)); - _named_colors.insert("lightskyblue", Color(0.53, 0.81, 0.98)); - _named_colors.insert("lightslategray", Color(0.47, 0.53, 0.60)); - _named_colors.insert("lightsteelblue", Color(0.69, 0.77, 0.87)); - _named_colors.insert("lightyellow", Color(1.00, 1.00, 0.88)); - _named_colors.insert("lime", Color(0.00, 1.00, 0.00)); - _named_colors.insert("limegreen", Color(0.20, 0.80, 0.20)); - _named_colors.insert("linen", Color(0.98, 0.94, 0.90)); - _named_colors.insert("magenta", Color(1.00, 0.00, 1.00)); - _named_colors.insert("maroon", Color(0.69, 0.19, 0.38)); - _named_colors.insert("webmaroon", Color(0.50, 0.00, 0.00)); - _named_colors.insert("mediumaquamarine", Color(0.40, 0.80, 0.67)); - _named_colors.insert("mediumblue", Color(0.00, 0.00, 0.80)); - _named_colors.insert("mediumorchid", Color(0.73, 0.33, 0.83)); - _named_colors.insert("mediumpurple", Color(0.58, 0.44, 0.86)); - _named_colors.insert("mediumseagreen", Color(0.24, 0.70, 0.44)); - _named_colors.insert("mediumslateblue", Color(0.48, 0.41, 0.93)); - _named_colors.insert("mediumspringgreen", Color(0.00, 0.98, 0.60)); - _named_colors.insert("mediumturquoise", Color(0.28, 0.82, 0.80)); - _named_colors.insert("mediumvioletred", Color(0.78, 0.08, 0.52)); - _named_colors.insert("midnightblue", Color(0.10, 0.10, 0.44)); - _named_colors.insert("mintcream", Color(0.96, 1.00, 0.98)); - _named_colors.insert("mistyrose", Color(1.00, 0.89, 0.88)); - _named_colors.insert("moccasin", Color(1.00, 0.89, 0.71)); - _named_colors.insert("navajowhite", Color(1.00, 0.87, 0.68)); - _named_colors.insert("navyblue", Color(0.00, 0.00, 0.50)); - _named_colors.insert("oldlace", Color(0.99, 0.96, 0.90)); - _named_colors.insert("olive", Color(0.50, 0.50, 0.00)); - _named_colors.insert("olivedrab", Color(0.42, 0.56, 0.14)); - _named_colors.insert("orange", Color(1.00, 0.65, 0.00)); - _named_colors.insert("orangered", Color(1.00, 0.27, 0.00)); - _named_colors.insert("orchid", Color(0.85, 0.44, 0.84)); - _named_colors.insert("palegoldenrod", Color(0.93, 0.91, 0.67)); - _named_colors.insert("palegreen", Color(0.60, 0.98, 0.60)); - _named_colors.insert("paleturquoise", Color(0.69, 0.93, 0.93)); - _named_colors.insert("palevioletred", Color(0.86, 0.44, 0.58)); - _named_colors.insert("papayawhip", Color(1.00, 0.94, 0.84)); - _named_colors.insert("peachpuff", Color(1.00, 0.85, 0.73)); - _named_colors.insert("peru", Color(0.80, 0.52, 0.25)); - _named_colors.insert("pink", Color(1.00, 0.75, 0.80)); - _named_colors.insert("plum", Color(0.87, 0.63, 0.87)); - _named_colors.insert("powderblue", Color(0.69, 0.88, 0.90)); - _named_colors.insert("purple", Color(0.63, 0.13, 0.94)); - _named_colors.insert("webpurple", Color(0.50, 0.00, 0.50)); - _named_colors.insert("rebeccapurple", Color(0.40, 0.20, 0.60)); - _named_colors.insert("red", Color(1.00, 0.00, 0.00)); - _named_colors.insert("rosybrown", Color(0.74, 0.56, 0.56)); - _named_colors.insert("royalblue", Color(0.25, 0.41, 0.88)); - _named_colors.insert("saddlebrown", Color(0.55, 0.27, 0.07)); - _named_colors.insert("salmon", Color(0.98, 0.50, 0.45)); - _named_colors.insert("sandybrown", Color(0.96, 0.64, 0.38)); - _named_colors.insert("seagreen", Color(0.18, 0.55, 0.34)); - _named_colors.insert("seashell", Color(1.00, 0.96, 0.93)); - _named_colors.insert("sienna", Color(0.63, 0.32, 0.18)); - _named_colors.insert("silver", Color(0.75, 0.75, 0.75)); - _named_colors.insert("skyblue", Color(0.53, 0.81, 0.92)); - _named_colors.insert("slateblue", Color(0.42, 0.35, 0.80)); - _named_colors.insert("slategray", Color(0.44, 0.50, 0.56)); - _named_colors.insert("snow", Color(1.00, 0.98, 0.98)); - _named_colors.insert("springgreen", Color(0.00, 1.00, 0.50)); - _named_colors.insert("steelblue", Color(0.27, 0.51, 0.71)); - _named_colors.insert("tan", Color(0.82, 0.71, 0.55)); - _named_colors.insert("teal", Color(0.00, 0.50, 0.50)); - _named_colors.insert("thistle", Color(0.85, 0.75, 0.85)); - _named_colors.insert("tomato", Color(1.00, 0.39, 0.28)); - _named_colors.insert("turquoise", Color(0.25, 0.88, 0.82)); - _named_colors.insert("transparent", Color(1.00, 1.00, 1.00, 0.00)); - _named_colors.insert("violet", Color(0.93, 0.51, 0.93)); - _named_colors.insert("wheat", Color(0.96, 0.87, 0.70)); - _named_colors.insert("white", Color(1.00, 1.00, 1.00)); - _named_colors.insert("whitesmoke", Color(0.96, 0.96, 0.96)); - _named_colors.insert("yellow", Color(1.00, 1.00, 0.00)); - _named_colors.insert("yellowgreen", Color(0.60, 0.80, 0.20)); -} diff --git a/core/config/SCsub b/core/config/SCsub new file mode 100644 index 0000000000..bf70285490 --- /dev/null +++ b/core/config/SCsub @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +Import("env") + +env_config = env.Clone() + +env_config.add_source_files(env.core_sources, "*.cpp") diff --git a/core/engine.cpp b/core/config/engine.cpp index d08cf92ecb..2360d66438 100644 --- a/core/engine.cpp +++ b/core/config/engine.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -181,6 +181,14 @@ String Engine::get_license_text() const { return String(GODOT_LICENSE_TEXT); } +bool Engine::is_abort_on_gpu_errors_enabled() const { + return abort_on_gpu_errors; +} + +bool Engine::is_validation_layers_enabled() const { + return use_validation_layers; +} + void Engine::add_singleton(const Singleton &p_singleton) { singletons.push_back(p_singleton); singleton_ptrs[p_singleton.name] = p_singleton.ptr; @@ -208,10 +216,17 @@ Engine *Engine::get_singleton() { return singleton; } -bool Engine::is_abort_on_gpu_errors_enabled() const { - return abort_on_gpu_errors; -} - Engine::Engine() { singleton = this; } + +Engine::Singleton::Singleton(const StringName &p_name, Object *p_ptr) : + name(p_name), + ptr(p_ptr) { +#ifdef DEBUG_ENABLED + Reference *ref = Object::cast_to<Reference>(p_ptr); + if (ref && !ref->is_referenced()) { + WARN_PRINT("You must use Ref<> to ensure the lifetime of a Reference object intended to be used as a singleton."); + } +#endif +} diff --git a/core/engine.h b/core/config/engine.h index fef330c0c1..a9080e3dfd 100644 --- a/core/engine.h +++ b/core/config/engine.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,20 +31,17 @@ #ifndef ENGINE_H #define ENGINE_H -#include "core/list.h" #include "core/os/main_loop.h" -#include "core/ustring.h" -#include "core/vector.h" +#include "core/string/ustring.h" +#include "core/templates/list.h" +#include "core/templates/vector.h" class Engine { public: struct Singleton { StringName name; Object *ptr; - Singleton(const StringName &p_name = StringName(), Object *p_ptr = nullptr) : - name(p_name), - ptr(p_ptr) { - } + Singleton(const StringName &p_name = StringName(), Object *p_ptr = nullptr); }; private: @@ -53,19 +50,19 @@ private: uint64_t frames_drawn = 0; uint32_t _frame_delay = 0; uint64_t _frame_ticks = 0; - float _frame_step = 0; + float _process_step = 0; int ips = 60; float physics_jitter_fix = 0.5; float _fps = 1; int _target_fps = 0; float _time_scale = 1.0; - bool _pixel_snap = false; uint64_t _physics_frames = 0; float _physics_interpolation_fraction = 0.0f; bool abort_on_gpu_errors = false; + bool use_validation_layers = false; - uint64_t _idle_frames = 0; + uint64_t _process_frames = 0; bool _in_physics = false; List<Singleton> singletons; @@ -92,10 +89,10 @@ public: uint64_t get_frames_drawn(); uint64_t get_physics_frames() const { return _physics_frames; } - uint64_t get_idle_frames() const { return _idle_frames; } + uint64_t get_process_frames() const { return _process_frames; } bool is_in_physics_frame() const { return _in_physics; } - uint64_t get_idle_frame_ticks() const { return _frame_ticks; } - float get_idle_frame_step() const { return _frame_step; } + uint64_t get_frame_ticks() const { return _frame_ticks; } + float get_process_step() const { return _process_step; } float get_physics_interpolation_fraction() const { return _physics_interpolation_fraction; } void set_time_scale(float p_scale); @@ -109,8 +106,6 @@ public: bool has_singleton(const String &p_name) const; Object *get_singleton_object(const String &p_name) const; - _FORCE_INLINE_ bool get_use_pixel_snap() const { return _pixel_snap; } - #ifdef TOOLS_ENABLED _FORCE_INLINE_ void set_editor_hint(bool p_enabled) { editor_hint = p_enabled; } _FORCE_INLINE_ bool is_editor_hint() const { return editor_hint; } @@ -127,6 +122,7 @@ public: String get_license_text() const; bool is_abort_on_gpu_errors_enabled() const; + bool is_validation_layers_enabled() const; Engine(); virtual ~Engine() {} diff --git a/core/project_settings.cpp b/core/config/project_settings.cpp index 90f56694c2..70e8133eaa 100644 --- a/core/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "project_settings.h" -#include "core/bind/core_bind.h" +#include "core/core_bind.h" #include "core/core_string_names.h" #include "core/io/file_access_network.h" #include "core/io/file_access_pack.h" @@ -39,7 +39,7 @@ #include "core/os/file_access.h" #include "core/os/keyboard.h" #include "core/os/os.h" -#include "core/variant_parser.h" +#include "core/variant/variant_parser.h" #include <zlib.h> @@ -402,7 +402,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b #ifdef OSX_ENABLED if (!found) { // Attempt to load PCK from macOS .app bundle resources. - found = _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_basename + ".pck")); + found = _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_basename + ".pck")) || _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().plus_file(exec_filename + ".pck")); } #endif @@ -524,10 +524,6 @@ bool ProjectSettings::has_setting(String p_var) const { return props.has(p_var); } -void ProjectSettings::set_registering_order(bool p_enable) { - registering_order = p_enable; -} - Error ProjectSettings::_load_settings_binary(const String &p_path) { Error err; FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); @@ -629,19 +625,26 @@ Error ProjectSettings::_load_settings_text(const String &p_path) { } Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path, const String &p_bin_path) { - // Attempt first to load the text-based project.godot file - Error err_text = _load_settings_text(p_text_path); - if (err_text == OK) { + // Attempt first to load the binary project.godot file. + Error err = _load_settings_binary(p_bin_path); + if (err == OK) { + return OK; + } else if (err != ERR_FILE_NOT_FOUND) { + // If the file exists but can't be loaded, we want to know it. + ERR_PRINT("Couldn't load file '" + p_bin_path + "', error code " + itos(err) + "."); + return err; + } + + // Fallback to text-based project.godot file if binary was not found. + err = _load_settings_text(p_text_path); + if (err == OK) { return OK; - } else if (err_text != ERR_FILE_NOT_FOUND) { - // If the text-based file exists but can't be loaded, we want to know it - ERR_PRINT("Couldn't load file '" + p_text_path + "', error code " + itos(err_text) + "."); - return err_text; + } else if (err != ERR_FILE_NOT_FOUND) { + ERR_PRINT("Couldn't load file '" + p_text_path + "', error code " + itos(err) + "."); + return err; } - // Fallback to binary project.binary file if text-based was not found - Error err_bin = _load_settings_binary(p_bin_path); - return err_bin; + return err; } int ProjectSettings::get_order(const String &p_name) const { diff --git a/core/project_settings.h b/core/config/project_settings.h index 6cbb02d30e..59c56c23c2 100644 --- a/core/project_settings.h +++ b/core/config/project_settings.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +31,9 @@ #ifndef PROJECT_SETTINGS_H #define PROJECT_SETTINGS_H -#include "core/object.h" +#include "core/object/class_db.h" #include "core/os/thread_safe.h" -#include "core/set.h" +#include "core/templates/set.h" class ProjectSettings : public Object { GDCLASS(ProjectSettings, Object); @@ -76,7 +76,6 @@ protected: } }; - bool registering_order = true; int last_order = NO_BUILTIN_ORDER_BASE; int last_builtin_order = 0; Map<StringName, VariantContainer> props; @@ -160,8 +159,6 @@ public: bool is_using_datapack() const; - void set_registering_order(bool p_enable); - bool has_custom_feature(const String &p_feature) const; Map<StringName, AutoloadInfo> get_autoload_list() const; diff --git a/core/bind/core_bind.cpp b/core/core_bind.cpp index baf5d4b928..46f05bdaf5 100644 --- a/core/bind/core_bind.cpp +++ b/core/core_bind.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,6 +30,7 @@ #include "core_bind.h" +#include "core/config/project_settings.h" #include "core/crypto/crypto_core.h" #include "core/debugger/engine_debugger.h" #include "core/io/file_access_compressed.h" @@ -40,7 +41,6 @@ #include "core/math/geometry_3d.h" #include "core/os/keyboard.h" #include "core/os/os.h" -#include "core/project_settings.h" /** * Time constants borrowed from loc_time.h @@ -542,9 +542,9 @@ void _OS::dump_memory_to_file(const String &p_file) { struct _OSCoreBindImg { String path; Size2 size; - int fmt; + int fmt = 0; ObjectID id; - int vram; + int vram = 0; bool operator<(const _OSCoreBindImg &p_img) const { return vram == p_img.vram ? id < p_img.id : vram > p_img.vram; } }; @@ -2278,8 +2278,8 @@ uint64_t _Engine::get_physics_frames() const { return Engine::get_singleton()->get_physics_frames(); } -uint64_t _Engine::get_idle_frames() const { - return Engine::get_singleton()->get_idle_frames(); +uint64_t _Engine::get_process_frames() const { + return Engine::get_singleton()->get_process_frames(); } void _Engine::set_time_scale(float p_scale) { @@ -2358,7 +2358,7 @@ void _Engine::_bind_methods() { ClassDB::bind_method(D_METHOD("get_frames_drawn"), &_Engine::get_frames_drawn); ClassDB::bind_method(D_METHOD("get_frames_per_second"), &_Engine::get_frames_per_second); ClassDB::bind_method(D_METHOD("get_physics_frames"), &_Engine::get_physics_frames); - ClassDB::bind_method(D_METHOD("get_idle_frames"), &_Engine::get_idle_frames); + ClassDB::bind_method(D_METHOD("get_process_frames"), &_Engine::get_process_frames); ClassDB::bind_method(D_METHOD("get_main_loop"), &_Engine::get_main_loop); diff --git a/core/bind/core_bind.h b/core/core_bind.h index e75e740cd5..30dfa2d7a8 100644 --- a/core/bind/core_bind.h +++ b/core/core_bind.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef CORE_BIND_H #define CORE_BIND_H -#include "core/image.h" #include "core/io/compression.h" +#include "core/io/image.h" #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" #include "core/os/dir_access.h" @@ -83,7 +83,6 @@ protected: public: enum SaverFlags { - FLAG_RELATIVE_PATHS = 1, FLAG_BUNDLE_RESOURCES = 2, FLAG_CHANGE_PATH = 4, @@ -361,7 +360,6 @@ protected: public: enum ModeFlags { - READ = 1, WRITE = 2, READ_WRITE = 3, @@ -494,8 +492,8 @@ public: virtual ~_Directory(); private: - bool _list_skip_navigational; - bool _list_skip_hidden; + bool _list_skip_navigational = false; + bool _list_skip_hidden = false; }; class _Marshalls : public Object { @@ -561,7 +559,6 @@ protected: public: enum Priority { - PRIORITY_LOW, PRIORITY_NORMAL, PRIORITY_HIGH, @@ -638,7 +635,7 @@ public: float get_frames_per_second() const; uint64_t get_physics_frames() const; - uint64_t get_idle_frames() const; + uint64_t get_process_frames() const; int get_frames_drawn(); diff --git a/core/core_constants.cpp b/core/core_constants.cpp new file mode 100644 index 0000000000..3df121b9cb --- /dev/null +++ b/core/core_constants.cpp @@ -0,0 +1,659 @@ +/*************************************************************************/ +/* core_constants.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "core_constants.h" + +#include "core/input/input_event.h" +#include "core/object/class_db.h" +#include "core/os/keyboard.h" +#include "core/variant/variant.h" + +struct _CoreConstant { +#ifdef DEBUG_METHODS_ENABLED + StringName enum_name; + bool ignore_value_in_docs = false; +#endif + const char *name; + int value = 0; + + _CoreConstant() {} + +#ifdef DEBUG_METHODS_ENABLED + _CoreConstant(const StringName &p_enum_name, const char *p_name, int p_value, bool p_ignore_value_in_docs = false) : + enum_name(p_enum_name), + ignore_value_in_docs(p_ignore_value_in_docs), + name(p_name), + value(p_value) { + } +#else + _CoreConstant(const char *p_name, int p_value) : + name(p_name), + value(p_value) { + } +#endif +}; + +static Vector<_CoreConstant> _global_constants; + +#ifdef DEBUG_METHODS_ENABLED + +#define BIND_CORE_CONSTANT(m_constant) \ + _global_constants.push_back(_CoreConstant(StringName(), #m_constant, m_constant)); + +#define BIND_CORE_ENUM_CONSTANT(m_constant) \ + _global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant)); + +#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \ + _global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_constant, #m_constant), m_custom_name, m_constant)); + +#define BIND_CORE_CONSTANT_NO_VAL(m_constant) \ + _global_constants.push_back(_CoreConstant(StringName(), #m_constant, m_constant, true)); + +#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \ + _global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant, true)); + +#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \ + _global_constants.push_back(_CoreConstant(__constant_get_enum_name(m_constant, #m_constant), m_custom_name, m_constant, true)); + +#else + +#define BIND_CORE_CONSTANT(m_constant) \ + _global_constants.push_back(_CoreConstant(#m_constant, m_constant)); + +#define BIND_CORE_ENUM_CONSTANT(m_constant) \ + _global_constants.push_back(_CoreConstant(#m_constant, m_constant)); + +#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \ + _global_constants.push_back(_CoreConstant(m_custom_name, m_constant)); + +#define BIND_CORE_CONSTANT_NO_VAL(m_constant) \ + _global_constants.push_back(_CoreConstant(#m_constant, m_constant)); + +#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \ + _global_constants.push_back(_CoreConstant(#m_constant, m_constant)); + +#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \ + _global_constants.push_back(_CoreConstant(m_custom_name, m_constant)); + +#endif + +VARIANT_ENUM_CAST(KeyList); +VARIANT_ENUM_CAST(KeyModifierMask); +VARIANT_ENUM_CAST(ButtonList); +VARIANT_ENUM_CAST(JoyButtonList); +VARIANT_ENUM_CAST(JoyAxisList); +VARIANT_ENUM_CAST(MidiMessageList); + +void register_global_constants() { + BIND_CORE_ENUM_CONSTANT(SIDE_LEFT); + BIND_CORE_ENUM_CONSTANT(SIDE_TOP); + BIND_CORE_ENUM_CONSTANT(SIDE_RIGHT); + BIND_CORE_ENUM_CONSTANT(SIDE_BOTTOM); + + BIND_CORE_ENUM_CONSTANT(CORNER_TOP_LEFT); + BIND_CORE_ENUM_CONSTANT(CORNER_TOP_RIGHT); + BIND_CORE_ENUM_CONSTANT(CORNER_BOTTOM_RIGHT); + BIND_CORE_ENUM_CONSTANT(CORNER_BOTTOM_LEFT); + + BIND_CORE_ENUM_CONSTANT(VERTICAL); + BIND_CORE_ENUM_CONSTANT(HORIZONTAL); + + BIND_CORE_ENUM_CONSTANT(HALIGN_LEFT); + BIND_CORE_ENUM_CONSTANT(HALIGN_CENTER); + BIND_CORE_ENUM_CONSTANT(HALIGN_RIGHT); + BIND_CORE_ENUM_CONSTANT(HALIGN_FILL); + + BIND_CORE_ENUM_CONSTANT(VALIGN_TOP); + BIND_CORE_ENUM_CONSTANT(VALIGN_CENTER); + BIND_CORE_ENUM_CONSTANT(VALIGN_BOTTOM); + + // huge list of keys + BIND_CORE_CONSTANT(SPKEY); + + BIND_CORE_ENUM_CONSTANT(KEY_ESCAPE); + BIND_CORE_ENUM_CONSTANT(KEY_TAB); + BIND_CORE_ENUM_CONSTANT(KEY_BACKTAB); + BIND_CORE_ENUM_CONSTANT(KEY_BACKSPACE); + BIND_CORE_ENUM_CONSTANT(KEY_ENTER); + BIND_CORE_ENUM_CONSTANT(KEY_KP_ENTER); + BIND_CORE_ENUM_CONSTANT(KEY_INSERT); + BIND_CORE_ENUM_CONSTANT(KEY_DELETE); + BIND_CORE_ENUM_CONSTANT(KEY_PAUSE); + BIND_CORE_ENUM_CONSTANT(KEY_PRINT); + BIND_CORE_ENUM_CONSTANT(KEY_SYSREQ); + BIND_CORE_ENUM_CONSTANT(KEY_CLEAR); + BIND_CORE_ENUM_CONSTANT(KEY_HOME); + BIND_CORE_ENUM_CONSTANT(KEY_END); + BIND_CORE_ENUM_CONSTANT(KEY_LEFT); + BIND_CORE_ENUM_CONSTANT(KEY_UP); + BIND_CORE_ENUM_CONSTANT(KEY_RIGHT); + BIND_CORE_ENUM_CONSTANT(KEY_DOWN); + BIND_CORE_ENUM_CONSTANT(KEY_PAGEUP); + BIND_CORE_ENUM_CONSTANT(KEY_PAGEDOWN); + BIND_CORE_ENUM_CONSTANT(KEY_SHIFT); + BIND_CORE_ENUM_CONSTANT(KEY_CONTROL); + BIND_CORE_ENUM_CONSTANT(KEY_META); + BIND_CORE_ENUM_CONSTANT(KEY_ALT); + BIND_CORE_ENUM_CONSTANT(KEY_CAPSLOCK); + BIND_CORE_ENUM_CONSTANT(KEY_NUMLOCK); + BIND_CORE_ENUM_CONSTANT(KEY_SCROLLLOCK); + BIND_CORE_ENUM_CONSTANT(KEY_F1); + BIND_CORE_ENUM_CONSTANT(KEY_F2); + BIND_CORE_ENUM_CONSTANT(KEY_F3); + BIND_CORE_ENUM_CONSTANT(KEY_F4); + BIND_CORE_ENUM_CONSTANT(KEY_F5); + BIND_CORE_ENUM_CONSTANT(KEY_F6); + BIND_CORE_ENUM_CONSTANT(KEY_F7); + BIND_CORE_ENUM_CONSTANT(KEY_F8); + BIND_CORE_ENUM_CONSTANT(KEY_F9); + BIND_CORE_ENUM_CONSTANT(KEY_F10); + BIND_CORE_ENUM_CONSTANT(KEY_F11); + BIND_CORE_ENUM_CONSTANT(KEY_F12); + BIND_CORE_ENUM_CONSTANT(KEY_F13); + BIND_CORE_ENUM_CONSTANT(KEY_F14); + BIND_CORE_ENUM_CONSTANT(KEY_F15); + BIND_CORE_ENUM_CONSTANT(KEY_F16); + BIND_CORE_ENUM_CONSTANT(KEY_KP_MULTIPLY); + BIND_CORE_ENUM_CONSTANT(KEY_KP_DIVIDE); + BIND_CORE_ENUM_CONSTANT(KEY_KP_SUBTRACT); + BIND_CORE_ENUM_CONSTANT(KEY_KP_PERIOD); + BIND_CORE_ENUM_CONSTANT(KEY_KP_ADD); + BIND_CORE_ENUM_CONSTANT(KEY_KP_0); + BIND_CORE_ENUM_CONSTANT(KEY_KP_1); + BIND_CORE_ENUM_CONSTANT(KEY_KP_2); + BIND_CORE_ENUM_CONSTANT(KEY_KP_3); + BIND_CORE_ENUM_CONSTANT(KEY_KP_4); + BIND_CORE_ENUM_CONSTANT(KEY_KP_5); + BIND_CORE_ENUM_CONSTANT(KEY_KP_6); + BIND_CORE_ENUM_CONSTANT(KEY_KP_7); + BIND_CORE_ENUM_CONSTANT(KEY_KP_8); + BIND_CORE_ENUM_CONSTANT(KEY_KP_9); + BIND_CORE_ENUM_CONSTANT(KEY_SUPER_L); + BIND_CORE_ENUM_CONSTANT(KEY_SUPER_R); + BIND_CORE_ENUM_CONSTANT(KEY_MENU); + BIND_CORE_ENUM_CONSTANT(KEY_HYPER_L); + BIND_CORE_ENUM_CONSTANT(KEY_HYPER_R); + BIND_CORE_ENUM_CONSTANT(KEY_HELP); + BIND_CORE_ENUM_CONSTANT(KEY_DIRECTION_L); + BIND_CORE_ENUM_CONSTANT(KEY_DIRECTION_R); + BIND_CORE_ENUM_CONSTANT(KEY_BACK); + BIND_CORE_ENUM_CONSTANT(KEY_FORWARD); + BIND_CORE_ENUM_CONSTANT(KEY_STOP); + BIND_CORE_ENUM_CONSTANT(KEY_REFRESH); + BIND_CORE_ENUM_CONSTANT(KEY_VOLUMEDOWN); + BIND_CORE_ENUM_CONSTANT(KEY_VOLUMEMUTE); + BIND_CORE_ENUM_CONSTANT(KEY_VOLUMEUP); + BIND_CORE_ENUM_CONSTANT(KEY_BASSBOOST); + BIND_CORE_ENUM_CONSTANT(KEY_BASSUP); + BIND_CORE_ENUM_CONSTANT(KEY_BASSDOWN); + BIND_CORE_ENUM_CONSTANT(KEY_TREBLEUP); + BIND_CORE_ENUM_CONSTANT(KEY_TREBLEDOWN); + BIND_CORE_ENUM_CONSTANT(KEY_MEDIAPLAY); + BIND_CORE_ENUM_CONSTANT(KEY_MEDIASTOP); + BIND_CORE_ENUM_CONSTANT(KEY_MEDIAPREVIOUS); + BIND_CORE_ENUM_CONSTANT(KEY_MEDIANEXT); + BIND_CORE_ENUM_CONSTANT(KEY_MEDIARECORD); + BIND_CORE_ENUM_CONSTANT(KEY_HOMEPAGE); + BIND_CORE_ENUM_CONSTANT(KEY_FAVORITES); + BIND_CORE_ENUM_CONSTANT(KEY_SEARCH); + BIND_CORE_ENUM_CONSTANT(KEY_STANDBY); + BIND_CORE_ENUM_CONSTANT(KEY_OPENURL); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHMAIL); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHMEDIA); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH0); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH1); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH2); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH3); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH4); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH5); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH6); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH7); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH8); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCH9); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHA); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHB); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHC); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHD); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHE); + BIND_CORE_ENUM_CONSTANT(KEY_LAUNCHF); + + BIND_CORE_ENUM_CONSTANT(KEY_UNKNOWN); + BIND_CORE_ENUM_CONSTANT(KEY_SPACE); + BIND_CORE_ENUM_CONSTANT(KEY_EXCLAM); + BIND_CORE_ENUM_CONSTANT(KEY_QUOTEDBL); + BIND_CORE_ENUM_CONSTANT(KEY_NUMBERSIGN); + BIND_CORE_ENUM_CONSTANT(KEY_DOLLAR); + BIND_CORE_ENUM_CONSTANT(KEY_PERCENT); + BIND_CORE_ENUM_CONSTANT(KEY_AMPERSAND); + BIND_CORE_ENUM_CONSTANT(KEY_APOSTROPHE); + BIND_CORE_ENUM_CONSTANT(KEY_PARENLEFT); + BIND_CORE_ENUM_CONSTANT(KEY_PARENRIGHT); + BIND_CORE_ENUM_CONSTANT(KEY_ASTERISK); + BIND_CORE_ENUM_CONSTANT(KEY_PLUS); + BIND_CORE_ENUM_CONSTANT(KEY_COMMA); + BIND_CORE_ENUM_CONSTANT(KEY_MINUS); + BIND_CORE_ENUM_CONSTANT(KEY_PERIOD); + BIND_CORE_ENUM_CONSTANT(KEY_SLASH); + BIND_CORE_ENUM_CONSTANT(KEY_0); + BIND_CORE_ENUM_CONSTANT(KEY_1); + BIND_CORE_ENUM_CONSTANT(KEY_2); + BIND_CORE_ENUM_CONSTANT(KEY_3); + BIND_CORE_ENUM_CONSTANT(KEY_4); + BIND_CORE_ENUM_CONSTANT(KEY_5); + BIND_CORE_ENUM_CONSTANT(KEY_6); + BIND_CORE_ENUM_CONSTANT(KEY_7); + BIND_CORE_ENUM_CONSTANT(KEY_8); + BIND_CORE_ENUM_CONSTANT(KEY_9); + BIND_CORE_ENUM_CONSTANT(KEY_COLON); + BIND_CORE_ENUM_CONSTANT(KEY_SEMICOLON); + BIND_CORE_ENUM_CONSTANT(KEY_LESS); + BIND_CORE_ENUM_CONSTANT(KEY_EQUAL); + BIND_CORE_ENUM_CONSTANT(KEY_GREATER); + BIND_CORE_ENUM_CONSTANT(KEY_QUESTION); + BIND_CORE_ENUM_CONSTANT(KEY_AT); + BIND_CORE_ENUM_CONSTANT(KEY_A); + BIND_CORE_ENUM_CONSTANT(KEY_B); + BIND_CORE_ENUM_CONSTANT(KEY_C); + BIND_CORE_ENUM_CONSTANT(KEY_D); + BIND_CORE_ENUM_CONSTANT(KEY_E); + BIND_CORE_ENUM_CONSTANT(KEY_F); + BIND_CORE_ENUM_CONSTANT(KEY_G); + BIND_CORE_ENUM_CONSTANT(KEY_H); + BIND_CORE_ENUM_CONSTANT(KEY_I); + BIND_CORE_ENUM_CONSTANT(KEY_J); + BIND_CORE_ENUM_CONSTANT(KEY_K); + BIND_CORE_ENUM_CONSTANT(KEY_L); + BIND_CORE_ENUM_CONSTANT(KEY_M); + BIND_CORE_ENUM_CONSTANT(KEY_N); + BIND_CORE_ENUM_CONSTANT(KEY_O); + BIND_CORE_ENUM_CONSTANT(KEY_P); + BIND_CORE_ENUM_CONSTANT(KEY_Q); + BIND_CORE_ENUM_CONSTANT(KEY_R); + BIND_CORE_ENUM_CONSTANT(KEY_S); + BIND_CORE_ENUM_CONSTANT(KEY_T); + BIND_CORE_ENUM_CONSTANT(KEY_U); + BIND_CORE_ENUM_CONSTANT(KEY_V); + BIND_CORE_ENUM_CONSTANT(KEY_W); + BIND_CORE_ENUM_CONSTANT(KEY_X); + BIND_CORE_ENUM_CONSTANT(KEY_Y); + BIND_CORE_ENUM_CONSTANT(KEY_Z); + BIND_CORE_ENUM_CONSTANT(KEY_BRACKETLEFT); + BIND_CORE_ENUM_CONSTANT(KEY_BACKSLASH); + BIND_CORE_ENUM_CONSTANT(KEY_BRACKETRIGHT); + BIND_CORE_ENUM_CONSTANT(KEY_ASCIICIRCUM); + BIND_CORE_ENUM_CONSTANT(KEY_UNDERSCORE); + BIND_CORE_ENUM_CONSTANT(KEY_QUOTELEFT); + BIND_CORE_ENUM_CONSTANT(KEY_BRACELEFT); + BIND_CORE_ENUM_CONSTANT(KEY_BAR); + BIND_CORE_ENUM_CONSTANT(KEY_BRACERIGHT); + BIND_CORE_ENUM_CONSTANT(KEY_ASCIITILDE); + BIND_CORE_ENUM_CONSTANT(KEY_NOBREAKSPACE); + BIND_CORE_ENUM_CONSTANT(KEY_EXCLAMDOWN); + BIND_CORE_ENUM_CONSTANT(KEY_CENT); + BIND_CORE_ENUM_CONSTANT(KEY_STERLING); + BIND_CORE_ENUM_CONSTANT(KEY_CURRENCY); + BIND_CORE_ENUM_CONSTANT(KEY_YEN); + BIND_CORE_ENUM_CONSTANT(KEY_BROKENBAR); + BIND_CORE_ENUM_CONSTANT(KEY_SECTION); + BIND_CORE_ENUM_CONSTANT(KEY_DIAERESIS); + BIND_CORE_ENUM_CONSTANT(KEY_COPYRIGHT); + BIND_CORE_ENUM_CONSTANT(KEY_ORDFEMININE); + BIND_CORE_ENUM_CONSTANT(KEY_GUILLEMOTLEFT); + BIND_CORE_ENUM_CONSTANT(KEY_NOTSIGN); + BIND_CORE_ENUM_CONSTANT(KEY_HYPHEN); + BIND_CORE_ENUM_CONSTANT(KEY_REGISTERED); + BIND_CORE_ENUM_CONSTANT(KEY_MACRON); + BIND_CORE_ENUM_CONSTANT(KEY_DEGREE); + BIND_CORE_ENUM_CONSTANT(KEY_PLUSMINUS); + BIND_CORE_ENUM_CONSTANT(KEY_TWOSUPERIOR); + BIND_CORE_ENUM_CONSTANT(KEY_THREESUPERIOR); + BIND_CORE_ENUM_CONSTANT(KEY_ACUTE); + BIND_CORE_ENUM_CONSTANT(KEY_MU); + BIND_CORE_ENUM_CONSTANT(KEY_PARAGRAPH); + BIND_CORE_ENUM_CONSTANT(KEY_PERIODCENTERED); + BIND_CORE_ENUM_CONSTANT(KEY_CEDILLA); + BIND_CORE_ENUM_CONSTANT(KEY_ONESUPERIOR); + BIND_CORE_ENUM_CONSTANT(KEY_MASCULINE); + BIND_CORE_ENUM_CONSTANT(KEY_GUILLEMOTRIGHT); + BIND_CORE_ENUM_CONSTANT(KEY_ONEQUARTER); + BIND_CORE_ENUM_CONSTANT(KEY_ONEHALF); + BIND_CORE_ENUM_CONSTANT(KEY_THREEQUARTERS); + BIND_CORE_ENUM_CONSTANT(KEY_QUESTIONDOWN); + BIND_CORE_ENUM_CONSTANT(KEY_AGRAVE); + BIND_CORE_ENUM_CONSTANT(KEY_AACUTE); + BIND_CORE_ENUM_CONSTANT(KEY_ACIRCUMFLEX); + BIND_CORE_ENUM_CONSTANT(KEY_ATILDE); + BIND_CORE_ENUM_CONSTANT(KEY_ADIAERESIS); + BIND_CORE_ENUM_CONSTANT(KEY_ARING); + BIND_CORE_ENUM_CONSTANT(KEY_AE); + BIND_CORE_ENUM_CONSTANT(KEY_CCEDILLA); + BIND_CORE_ENUM_CONSTANT(KEY_EGRAVE); + BIND_CORE_ENUM_CONSTANT(KEY_EACUTE); + BIND_CORE_ENUM_CONSTANT(KEY_ECIRCUMFLEX); + BIND_CORE_ENUM_CONSTANT(KEY_EDIAERESIS); + BIND_CORE_ENUM_CONSTANT(KEY_IGRAVE); + BIND_CORE_ENUM_CONSTANT(KEY_IACUTE); + BIND_CORE_ENUM_CONSTANT(KEY_ICIRCUMFLEX); + BIND_CORE_ENUM_CONSTANT(KEY_IDIAERESIS); + BIND_CORE_ENUM_CONSTANT(KEY_ETH); + BIND_CORE_ENUM_CONSTANT(KEY_NTILDE); + BIND_CORE_ENUM_CONSTANT(KEY_OGRAVE); + BIND_CORE_ENUM_CONSTANT(KEY_OACUTE); + BIND_CORE_ENUM_CONSTANT(KEY_OCIRCUMFLEX); + BIND_CORE_ENUM_CONSTANT(KEY_OTILDE); + BIND_CORE_ENUM_CONSTANT(KEY_ODIAERESIS); + BIND_CORE_ENUM_CONSTANT(KEY_MULTIPLY); + BIND_CORE_ENUM_CONSTANT(KEY_OOBLIQUE); + BIND_CORE_ENUM_CONSTANT(KEY_UGRAVE); + BIND_CORE_ENUM_CONSTANT(KEY_UACUTE); + BIND_CORE_ENUM_CONSTANT(KEY_UCIRCUMFLEX); + BIND_CORE_ENUM_CONSTANT(KEY_UDIAERESIS); + BIND_CORE_ENUM_CONSTANT(KEY_YACUTE); + BIND_CORE_ENUM_CONSTANT(KEY_THORN); + BIND_CORE_ENUM_CONSTANT(KEY_SSHARP); + + BIND_CORE_ENUM_CONSTANT(KEY_DIVISION); + BIND_CORE_ENUM_CONSTANT(KEY_YDIAERESIS); + + BIND_CORE_ENUM_CONSTANT(KEY_CODE_MASK); + BIND_CORE_ENUM_CONSTANT(KEY_MODIFIER_MASK); + + BIND_CORE_ENUM_CONSTANT(KEY_MASK_SHIFT); + BIND_CORE_ENUM_CONSTANT(KEY_MASK_ALT); + BIND_CORE_ENUM_CONSTANT(KEY_MASK_META); + BIND_CORE_ENUM_CONSTANT(KEY_MASK_CTRL); + BIND_CORE_ENUM_CONSTANT_NO_VAL(KEY_MASK_CMD); + BIND_CORE_ENUM_CONSTANT(KEY_MASK_KPAD); + BIND_CORE_ENUM_CONSTANT(KEY_MASK_GROUP_SWITCH); + + // mouse + BIND_CORE_ENUM_CONSTANT(BUTTON_LEFT); + BIND_CORE_ENUM_CONSTANT(BUTTON_RIGHT); + BIND_CORE_ENUM_CONSTANT(BUTTON_MIDDLE); + BIND_CORE_ENUM_CONSTANT(BUTTON_XBUTTON1); + BIND_CORE_ENUM_CONSTANT(BUTTON_XBUTTON2); + BIND_CORE_ENUM_CONSTANT(BUTTON_WHEEL_UP); + BIND_CORE_ENUM_CONSTANT(BUTTON_WHEEL_DOWN); + BIND_CORE_ENUM_CONSTANT(BUTTON_WHEEL_LEFT); + BIND_CORE_ENUM_CONSTANT(BUTTON_WHEEL_RIGHT); + BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_LEFT); + BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_RIGHT); + BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_MIDDLE); + BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_XBUTTON1); + BIND_CORE_ENUM_CONSTANT(BUTTON_MASK_XBUTTON2); + + // Joypad buttons + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_INVALID); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_A); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_B); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_X); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_Y); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_BACK); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_GUIDE); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_START); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_LEFT_STICK); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_RIGHT_STICK); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_LEFT_SHOULDER); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_RIGHT_SHOULDER); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_UP); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_DOWN); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_LEFT); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_DPAD_RIGHT); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_SDL_MAX); + BIND_CORE_ENUM_CONSTANT(JOY_BUTTON_MAX); + + // Joypad axes + BIND_CORE_ENUM_CONSTANT(JOY_AXIS_INVALID); + BIND_CORE_ENUM_CONSTANT(JOY_AXIS_LEFT_X); + BIND_CORE_ENUM_CONSTANT(JOY_AXIS_LEFT_Y); + BIND_CORE_ENUM_CONSTANT(JOY_AXIS_RIGHT_X); + BIND_CORE_ENUM_CONSTANT(JOY_AXIS_RIGHT_Y); + BIND_CORE_ENUM_CONSTANT(JOY_AXIS_TRIGGER_LEFT); + BIND_CORE_ENUM_CONSTANT(JOY_AXIS_TRIGGER_RIGHT); + BIND_CORE_ENUM_CONSTANT(JOY_AXIS_SDL_MAX); + BIND_CORE_ENUM_CONSTANT(JOY_AXIS_MAX); + + // midi + BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_OFF); + BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_ON); + BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_AFTERTOUCH); + BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_CONTROL_CHANGE); + BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_PROGRAM_CHANGE); + BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_CHANNEL_PRESSURE); + BIND_CORE_ENUM_CONSTANT(MIDI_MESSAGE_PITCH_BEND); + + // error list + + BIND_CORE_ENUM_CONSTANT(OK); // (0) + BIND_CORE_ENUM_CONSTANT(FAILED); + BIND_CORE_ENUM_CONSTANT(ERR_UNAVAILABLE); + BIND_CORE_ENUM_CONSTANT(ERR_UNCONFIGURED); + BIND_CORE_ENUM_CONSTANT(ERR_UNAUTHORIZED); + BIND_CORE_ENUM_CONSTANT(ERR_PARAMETER_RANGE_ERROR); // (5) + BIND_CORE_ENUM_CONSTANT(ERR_OUT_OF_MEMORY); + BIND_CORE_ENUM_CONSTANT(ERR_FILE_NOT_FOUND); + BIND_CORE_ENUM_CONSTANT(ERR_FILE_BAD_DRIVE); + BIND_CORE_ENUM_CONSTANT(ERR_FILE_BAD_PATH); + BIND_CORE_ENUM_CONSTANT(ERR_FILE_NO_PERMISSION); // (10) + BIND_CORE_ENUM_CONSTANT(ERR_FILE_ALREADY_IN_USE); + BIND_CORE_ENUM_CONSTANT(ERR_FILE_CANT_OPEN); + BIND_CORE_ENUM_CONSTANT(ERR_FILE_CANT_WRITE); + BIND_CORE_ENUM_CONSTANT(ERR_FILE_CANT_READ); + BIND_CORE_ENUM_CONSTANT(ERR_FILE_UNRECOGNIZED); // (15) + BIND_CORE_ENUM_CONSTANT(ERR_FILE_CORRUPT); + BIND_CORE_ENUM_CONSTANT(ERR_FILE_MISSING_DEPENDENCIES); + BIND_CORE_ENUM_CONSTANT(ERR_FILE_EOF); + BIND_CORE_ENUM_CONSTANT(ERR_CANT_OPEN); + BIND_CORE_ENUM_CONSTANT(ERR_CANT_CREATE); // (20) + BIND_CORE_ENUM_CONSTANT(ERR_QUERY_FAILED); + BIND_CORE_ENUM_CONSTANT(ERR_ALREADY_IN_USE); + BIND_CORE_ENUM_CONSTANT(ERR_LOCKED); + BIND_CORE_ENUM_CONSTANT(ERR_TIMEOUT); + BIND_CORE_ENUM_CONSTANT(ERR_CANT_CONNECT); // (25) + BIND_CORE_ENUM_CONSTANT(ERR_CANT_RESOLVE); + BIND_CORE_ENUM_CONSTANT(ERR_CONNECTION_ERROR); + BIND_CORE_ENUM_CONSTANT(ERR_CANT_ACQUIRE_RESOURCE); + BIND_CORE_ENUM_CONSTANT(ERR_CANT_FORK); + BIND_CORE_ENUM_CONSTANT(ERR_INVALID_DATA); // (30) + BIND_CORE_ENUM_CONSTANT(ERR_INVALID_PARAMETER); + BIND_CORE_ENUM_CONSTANT(ERR_ALREADY_EXISTS); + BIND_CORE_ENUM_CONSTANT(ERR_DOES_NOT_EXIST); + BIND_CORE_ENUM_CONSTANT(ERR_DATABASE_CANT_READ); + BIND_CORE_ENUM_CONSTANT(ERR_DATABASE_CANT_WRITE); // (35) + BIND_CORE_ENUM_CONSTANT(ERR_COMPILATION_FAILED); + BIND_CORE_ENUM_CONSTANT(ERR_METHOD_NOT_FOUND); + BIND_CORE_ENUM_CONSTANT(ERR_LINK_FAILED); + BIND_CORE_ENUM_CONSTANT(ERR_SCRIPT_FAILED); + BIND_CORE_ENUM_CONSTANT(ERR_CYCLIC_LINK); // (40) + BIND_CORE_ENUM_CONSTANT(ERR_INVALID_DECLARATION); + BIND_CORE_ENUM_CONSTANT(ERR_DUPLICATE_SYMBOL); + BIND_CORE_ENUM_CONSTANT(ERR_PARSE_ERROR); + BIND_CORE_ENUM_CONSTANT(ERR_BUSY); + BIND_CORE_ENUM_CONSTANT(ERR_SKIP); // (45) + BIND_CORE_ENUM_CONSTANT(ERR_HELP); + BIND_CORE_ENUM_CONSTANT(ERR_BUG); + BIND_CORE_ENUM_CONSTANT(ERR_PRINTER_ON_FIRE); + + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NONE); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_RANGE); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_EXP_RANGE); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ENUM); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_EXP_EASING); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LENGTH); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_KEY_ACCEL); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_FLAGS); + + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_RENDER); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_PHYSICS); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_RENDER); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_PHYSICS); + + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_FILE); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_DIR); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_GLOBAL_FILE); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_GLOBAL_DIR); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_RESOURCE_TYPE); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MULTILINE_TEXT); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PLACEHOLDER_TEXT); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_COLOR_NO_ALPHA); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSY); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_TYPE_STRING); + + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_STORAGE); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NETWORK); + + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR_HELPER); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CHECKABLE); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CHECKED); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_INTERNATIONALIZED); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_GROUP); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_CATEGORY); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SUBGROUP); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NO_INSTANCE_STATE); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_RESTART_IF_CHANGED); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_VARIABLE); + + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT_INTL); + BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NOEDITOR); + + BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_NORMAL); + BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_EDITOR); + BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_NOSCRIPT); + BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_CONST); + BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_REVERSE); + BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_VIRTUAL); + BIND_CORE_ENUM_CONSTANT(METHOD_FLAG_FROM_SCRIPT); + BIND_CORE_ENUM_CONSTANT(METHOD_FLAGS_DEFAULT); + + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BOOL", Variant::BOOL); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_INT", Variant::INT); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_FLOAT", Variant::FLOAT); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_STRING", Variant::STRING); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR2", Variant::VECTOR2); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR2I", Variant::VECTOR2I); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_RECT2", Variant::RECT2); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_RECT2I", Variant::RECT2I); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3", Variant::VECTOR3); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3I", Variant::VECTOR3I); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM2D", Variant::TRANSFORM2D); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_PLANE", Variant::PLANE); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_QUAT", Variant::QUAT); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_AABB", Variant::AABB); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BASIS", Variant::BASIS); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM", Variant::TRANSFORM); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_COLOR", Variant::COLOR); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_STRING_NAME", Variant::STRING_NAME); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NODE_PATH", Variant::NODE_PATH); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_RID", Variant::RID); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_OBJECT", Variant::OBJECT); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_CALLABLE", Variant::CALLABLE); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_SIGNAL", Variant::SIGNAL); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_DICTIONARY", Variant::DICTIONARY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_ARRAY", Variant::ARRAY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_RAW_ARRAY", Variant::PACKED_BYTE_ARRAY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_INT32_ARRAY", Variant::PACKED_INT32_ARRAY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_INT64_ARRAY", Variant::PACKED_INT64_ARRAY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_FLOAT32_ARRAY", Variant::PACKED_FLOAT32_ARRAY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_FLOAT64_ARRAY", Variant::PACKED_FLOAT64_ARRAY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_STRING_ARRAY", Variant::PACKED_STRING_ARRAY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR2_ARRAY", Variant::PACKED_VECTOR2_ARRAY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3_ARRAY", Variant::PACKED_VECTOR3_ARRAY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_COLOR_ARRAY", Variant::PACKED_COLOR_ARRAY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_MAX", Variant::VARIANT_MAX); + + //comparison + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_EQUAL", Variant::OP_EQUAL); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_NOT_EQUAL", Variant::OP_NOT_EQUAL); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_LESS", Variant::OP_LESS); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_LESS_EQUAL", Variant::OP_LESS_EQUAL); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_GREATER", Variant::OP_GREATER); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_GREATER_EQUAL", Variant::OP_GREATER_EQUAL); + //mathematic + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_ADD", Variant::OP_ADD); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_SUBTRACT", Variant::OP_SUBTRACT); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_MULTIPLY", Variant::OP_MULTIPLY); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_DIVIDE", Variant::OP_DIVIDE); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_NEGATE", Variant::OP_NEGATE); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_POSITIVE", Variant::OP_POSITIVE); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_MODULE", Variant::OP_MODULE); + //bitwise + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_SHIFT_LEFT", Variant::OP_SHIFT_LEFT); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_SHIFT_RIGHT", Variant::OP_SHIFT_RIGHT); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_BIT_AND", Variant::OP_BIT_AND); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_BIT_OR", Variant::OP_BIT_OR); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_BIT_XOR", Variant::OP_BIT_XOR); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_BIT_NEGATE", Variant::OP_BIT_NEGATE); + //logic + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_AND", Variant::OP_AND); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_OR", Variant::OP_OR); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_XOR", Variant::OP_XOR); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_NOT", Variant::OP_NOT); + //containment + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_IN", Variant::OP_IN); + BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_MAX", Variant::OP_MAX); +} + +void unregister_global_constants() { + _global_constants.clear(); +} + +int CoreConstants::get_global_constant_count() { + return _global_constants.size(); +} + +#ifdef DEBUG_METHODS_ENABLED +StringName CoreConstants::get_global_constant_enum(int p_idx) { + return _global_constants[p_idx].enum_name; +} + +bool CoreConstants::get_ignore_value_in_docs(int p_idx) { + return _global_constants[p_idx].ignore_value_in_docs; +} +#else +StringName CoreConstants::get_global_constant_enum(int p_idx) { + return StringName(); +} + +bool CoreConstants::get_ignore_value_in_docs(int p_idx) { + return false; +} +#endif + +const char *CoreConstants::get_global_constant_name(int p_idx) { + return _global_constants[p_idx].name; +} + +int CoreConstants::get_global_constant_value(int p_idx) { + return _global_constants[p_idx].value; +} diff --git a/core/global_constants.h b/core/core_constants.h index 989633a6fa..deaf9ec60f 100644 --- a/core/global_constants.h +++ b/core/core_constants.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* global_constants.h */ +/* core_constants.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,12 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GLOBAL_CONSTANTS_H -#define GLOBAL_CONSTANTS_H +#ifndef CORE_CONSTANTS_H +#define CORE_CONSTANTS_H -#include "core/string_name.h" +#include "core/string/string_name.h" -class GlobalConstants { +class CoreConstants { public: static int get_global_constant_count(); static StringName get_global_constant_enum(int p_idx); diff --git a/core/core_string_names.cpp b/core/core_string_names.cpp index 6f86f107e6..18ac2a2d43 100644 --- a/core/core_string_names.cpp +++ b/core/core_string_names.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/core_string_names.h b/core/core_string_names.h index 43597ef301..b4e386f3bc 100644 --- a/core/core_string_names.h +++ b/core/core_string_names.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef CORE_STRING_NAMES_H #define CORE_STRING_NAMES_H -#include "core/string_name.h" +#include "core/string/string_name.h" class CoreStringNames { friend void register_core_types(); diff --git a/core/crypto/SCsub b/core/crypto/SCsub index da4a9c9381..4f3104d84b 100644 --- a/core/crypto/SCsub +++ b/core/crypto/SCsub @@ -6,6 +6,7 @@ env_crypto = env.Clone() is_builtin = env["builtin_mbedtls"] has_module = env["module_mbedtls_enabled"] +thirdparty_obj = [] if is_builtin or not has_module: # Use our headers for builtin or if the module is not going to be compiled. @@ -35,6 +36,16 @@ if not has_module: "godot_core_mbedtls_platform.c", ] thirdparty_mbedtls_sources = [thirdparty_mbedtls_dir + file for file in thirdparty_mbedtls_sources] - env_thirdparty.add_source_files(env.core_sources, thirdparty_mbedtls_sources) + env_thirdparty.add_source_files(thirdparty_obj, thirdparty_mbedtls_sources) + env.core_sources += thirdparty_obj -env_crypto.add_source_files(env.core_sources, "*.cpp") + +# Godot source files + +core_obj = [] + +env_crypto.add_source_files(core_obj, "*.cpp") +env.core_sources += core_obj + +# Needed to force rebuilding the core files when the thirdparty library is updated. +env.Depends(core_obj, thirdparty_obj) diff --git a/core/crypto/aes_context.cpp b/core/crypto/aes_context.cpp index 8ef1f4f1d4..b387aeb27d 100644 --- a/core/crypto/aes_context.cpp +++ b/core/crypto/aes_context.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -112,5 +112,4 @@ void AESContext::_bind_methods() { } AESContext::AESContext() { - mode = MODE_MAX; } diff --git a/core/crypto/aes_context.h b/core/crypto/aes_context.h index 006ecee2ad..cc00b18fd2 100644 --- a/core/crypto/aes_context.h +++ b/core/crypto/aes_context.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,7 @@ #define AES_CONTEXT_H #include "core/crypto/crypto_core.h" -#include "core/reference.h" +#include "core/object/reference.h" class AESContext : public Reference { GDCLASS(AESContext, Reference); @@ -47,7 +47,7 @@ public: }; private: - Mode mode; + Mode mode = MODE_MAX; CryptoCore::AESContext ctx; PackedByteArray iv; diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp index 29d02e11df..99f4fb232d 100644 --- a/core/crypto/crypto.cpp +++ b/core/crypto/crypto.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "crypto.h" -#include "core/engine.h" +#include "core/config/engine.h" #include "core/io/certs_compressed.gen.h" #include "core/io/compression.h" @@ -65,6 +65,22 @@ void X509Certificate::_bind_methods() { ClassDB::bind_method(D_METHOD("load", "path"), &X509Certificate::load); } +/// HMACContext + +void HMACContext::_bind_methods() { + ClassDB::bind_method(D_METHOD("start", "hash_type", "key"), &HMACContext::start); + ClassDB::bind_method(D_METHOD("update", "data"), &HMACContext::update); + ClassDB::bind_method(D_METHOD("finish"), &HMACContext::finish); +} + +HMACContext *(*HMACContext::_create)() = nullptr; +HMACContext *HMACContext::create() { + if (_create) { + return _create(); + } + ERR_FAIL_V_MSG(nullptr, "HMACContext is not available when the mbedtls module is disabled."); +} + /// Crypto void (*Crypto::_load_default_certificates)(String p_path) = nullptr; @@ -82,6 +98,35 @@ void Crypto::load_default_certificates(String p_path) { } } +PackedByteArray Crypto::hmac_digest(HashingContext::HashType p_hash_type, PackedByteArray p_key, PackedByteArray p_msg) { + Ref<HMACContext> ctx = Ref<HMACContext>(HMACContext::create()); + ERR_FAIL_COND_V_MSG(ctx.is_null(), PackedByteArray(), "HMAC is not available witout mbedtls module."); + Error err = ctx->start(p_hash_type, p_key); + ERR_FAIL_COND_V(err != OK, PackedByteArray()); + err = ctx->update(p_msg); + ERR_FAIL_COND_V(err != OK, PackedByteArray()); + return ctx->finish(); +} + +// Compares two HMACS for equality without leaking timing information in order to prevent timing attakcs. +// @see: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy +bool Crypto::constant_time_compare(PackedByteArray p_trusted, PackedByteArray p_received) { + const uint8_t *t = p_trusted.ptr(); + const uint8_t *r = p_received.ptr(); + int tlen = p_trusted.size(); + int rlen = p_received.size(); + // If the lengths are different then nothing else matters. + if (tlen != rlen) { + return false; + } + + uint8_t v = 0; + for (int i = 0; i < tlen; i++) { + v |= t[i] ^ r[i]; + } + return v == 0; +} + void Crypto::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_random_bytes", "size"), &Crypto::generate_random_bytes); ClassDB::bind_method(D_METHOD("generate_rsa", "size"), &Crypto::generate_rsa); @@ -90,6 +135,8 @@ void Crypto::_bind_methods() { ClassDB::bind_method(D_METHOD("verify", "hash_type", "hash", "signature", "key"), &Crypto::verify); ClassDB::bind_method(D_METHOD("encrypt", "key", "plaintext"), &Crypto::encrypt); ClassDB::bind_method(D_METHOD("decrypt", "key", "ciphertext"), &Crypto::decrypt); + ClassDB::bind_method(D_METHOD("hmac_digest", "hash_type", "key", "msg"), &Crypto::hmac_digest); + ClassDB::bind_method(D_METHOD("constant_time_compare", "trusted", "received"), &Crypto::constant_time_compare); } /// Resource loader/saver diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h index 916f7798eb..30d2129e3d 100644 --- a/core/crypto/crypto.h +++ b/core/crypto/crypto.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,10 +32,10 @@ #define CRYPTO_H #include "core/crypto/hashing_context.h" +#include "core/io/resource.h" #include "core/io/resource_loader.h" #include "core/io/resource_saver.h" -#include "core/reference.h" -#include "core/resource.h" +#include "core/object/reference.h" class CryptoKey : public Resource { GDCLASS(CryptoKey, Resource); @@ -67,6 +67,23 @@ public: virtual Error save(String p_path) = 0; }; +class HMACContext : public Reference { + GDCLASS(HMACContext, Reference); + +protected: + static void _bind_methods(); + static HMACContext *(*_create)(); + +public: + static HMACContext *create(); + + virtual Error start(HashingContext::HashType p_hash_type, PackedByteArray p_key) = 0; + virtual Error update(PackedByteArray p_data) = 0; + virtual PackedByteArray finish() = 0; + + HMACContext() {} +}; + class Crypto : public Reference { GDCLASS(Crypto, Reference); @@ -88,6 +105,12 @@ public: virtual Vector<uint8_t> encrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_plaintext) = 0; virtual Vector<uint8_t> decrypt(Ref<CryptoKey> p_key, Vector<uint8_t> p_ciphertext) = 0; + PackedByteArray hmac_digest(HashingContext::HashType p_hash_type, PackedByteArray p_key, PackedByteArray p_msg); + + // Compares two PackedByteArrays for equality without leaking timing information in order to prevent timing attacks. + // @see: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy + bool constant_time_compare(PackedByteArray p_trusted, PackedByteArray p_received); + Crypto() {} }; diff --git a/core/crypto/crypto_core.cpp b/core/crypto/crypto_core.cpp index 117e47d538..f90092056e 100644 --- a/core/crypto/crypto_core.cpp +++ b/core/crypto/crypto_core.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/crypto/crypto_core.h b/core/crypto/crypto_core.h index 9ab2871caa..27b380e838 100644 --- a/core/crypto/crypto_core.h +++ b/core/crypto/crypto_core.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,13 +31,13 @@ #ifndef CRYPTO_CORE_H #define CRYPTO_CORE_H -#include "core/reference.h" +#include "core/object/reference.h" class CryptoCore { public: class MD5Context { private: - void *ctx; // To include, or not to include... + void *ctx = nullptr; // To include, or not to include... public: MD5Context(); @@ -50,7 +50,7 @@ public: class SHA1Context { private: - void *ctx; // To include, or not to include... + void *ctx = nullptr; // To include, or not to include... public: SHA1Context(); @@ -63,7 +63,7 @@ public: class SHA256Context { private: - void *ctx; // To include, or not to include... + void *ctx = nullptr; // To include, or not to include... public: SHA256Context(); @@ -76,7 +76,7 @@ public: class AESContext { private: - void *ctx; // To include, or not to include... + void *ctx = nullptr; // To include, or not to include... public: AESContext(); diff --git a/core/crypto/hashing_context.cpp b/core/crypto/hashing_context.cpp index fb0dadfbab..070d2d4dd7 100644 --- a/core/crypto/hashing_context.cpp +++ b/core/crypto/hashing_context.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/crypto/hashing_context.h b/core/crypto/hashing_context.h index f9454fa891..892a48a4e8 100644 --- a/core/crypto/hashing_context.h +++ b/core/crypto/hashing_context.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef HASHING_CONTEXT_H #define HASHING_CONTEXT_H -#include "core/reference.h" +#include "core/object/reference.h" class HashingContext : public Reference { GDCLASS(HashingContext, Reference); @@ -45,7 +45,7 @@ public: private: void *ctx = nullptr; - HashType type; + HashType type = HASH_MD5; protected: static void _bind_methods(); diff --git a/core/debugger/debugger_marshalls.cpp b/core/debugger/debugger_marshalls.cpp index 3f949b0ae1..26f82c2658 100644 --- a/core/debugger/debugger_marshalls.cpp +++ b/core/debugger/debugger_marshalls.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -171,7 +171,7 @@ bool DebuggerMarshalls::ServersProfilerFrame::deserialize(const Array &p_arr) { } servers.push_back(si); } - CHECK_SIZE(p_arr, idx + 3, "ServersProfilerFrame"); + CHECK_SIZE(p_arr, idx + 1, "ServersProfilerFrame"); int func_size = p_arr[idx]; idx += 1; CHECK_SIZE(p_arr, idx + func_size, "ServersProfilerFrame"); diff --git a/core/debugger/debugger_marshalls.h b/core/debugger/debugger_marshalls.h index 7b7f4ac4b5..3e8c34d84b 100644 --- a/core/debugger/debugger_marshalls.h +++ b/core/debugger/debugger_marshalls.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef DEBUGGER_MARSHARLLS_H #define DEBUGGER_MARSHARLLS_H -#include "core/script_language.h" +#include "core/object/script_language.h" #include "servers/rendering_server.h" struct DebuggerMarshalls { @@ -148,7 +148,7 @@ struct DebuggerMarshalls { // Visual Profiler struct VisualProfilerFrame { - uint64_t frame_number; + uint64_t frame_number = 0; Vector<RS::FrameProfileArea> areas; Array serialize(); diff --git a/core/debugger/engine_debugger.cpp b/core/debugger/engine_debugger.cpp index 4bf31aa55f..895b8c23a9 100644 --- a/core/debugger/engine_debugger.cpp +++ b/core/debugger/engine_debugger.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -117,9 +117,9 @@ void EngineDebugger::line_poll() { poll_every++; } -void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_idle_ticks, uint64_t p_physics_ticks, float p_physics_frame_time) { +void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks, uint64_t p_physics_ticks, float p_physics_frame_time) { frame_time = USEC_TO_SEC(p_frame_ticks); - idle_time = USEC_TO_SEC(p_idle_ticks); + process_time = USEC_TO_SEC(p_process_ticks); physics_time = USEC_TO_SEC(p_physics_ticks); physics_frame_time = p_physics_frame_time; // Notify tick to running profilers @@ -128,14 +128,14 @@ void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_idle_ticks, ui if (!p.active || !p.tick) { continue; } - p.tick(p.data, frame_time, idle_time, physics_time, physics_frame_time); + p.tick(p.data, frame_time, process_time, physics_time, physics_frame_time); } singleton->poll_events(true); } void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints) { register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create); // TCP is the default protocol. Platforms/modules can add more. - if (p_uri.empty()) { + if (p_uri.is_empty()) { return; } if (p_uri == "local://") { diff --git a/core/debugger/engine_debugger.h b/core/debugger/engine_debugger.h index 8d5ebb2394..c6daea6e2f 100644 --- a/core/debugger/engine_debugger.h +++ b/core/debugger/engine_debugger.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,12 +31,12 @@ #ifndef ENGINE_DEBUGGER_H #define ENGINE_DEBUGGER_H -#include "core/array.h" -#include "core/map.h" -#include "core/string_name.h" -#include "core/ustring.h" -#include "core/variant.h" -#include "core/vector.h" +#include "core/string/string_name.h" +#include "core/string/ustring.h" +#include "core/templates/map.h" +#include "core/templates/vector.h" +#include "core/variant/array.h" +#include "core/variant/variant.h" class RemoteDebuggerPeer; class ScriptDebugger; @@ -44,7 +44,7 @@ class ScriptDebugger; class EngineDebugger { public: typedef void (*ProfilingToggle)(void *p_user, bool p_enable, const Array &p_opts); - typedef void (*ProfilingTick)(void *p_user, float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time); + typedef void (*ProfilingTick)(void *p_user, float p_frame_time, float p_process_time, float p_physics_time, float p_physics_frame_time); typedef void (*ProfilingAdd)(void *p_user, const Array &p_arr); typedef Error (*CaptureFunc)(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured); @@ -86,7 +86,7 @@ public: private: float frame_time = 0.0; - float idle_time = 0.0; + float process_time = 0.0; float physics_time = 0.0; float physics_frame_time = 0.0; @@ -120,7 +120,7 @@ public: static void register_uri_handler(const String &p_protocol, CreatePeerFunc p_func); - void iteration(uint64_t p_frame_ticks, uint64_t p_idle_ticks, uint64_t p_physics_ticks, float p_physics_frame_time); + void iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks, uint64_t p_physics_ticks, float p_physics_frame_time); void profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts = Array()); Error capture_parse(const StringName &p_name, const String &p_msg, const Array &p_args, bool &r_captured); diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp index 876be79418..1dd7e268a5 100644 --- a/core/debugger/local_debugger.cpp +++ b/core/debugger/local_debugger.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -117,7 +117,7 @@ struct LocalDebugger::ScriptsProfiler { void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { ScriptLanguage *script_lang = script_debugger->get_break_language(); - if (!target_function.empty()) { + if (!target_function.is_empty()) { String current_function = script_lang->debug_get_stack_level_function(0); if (current_function != target_function) { script_debugger->set_depth(0); @@ -259,7 +259,7 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { String source = breakpoint.first; int linenr = breakpoint.second; - if (source.empty()) { + if (source.is_empty()) { continue; } @@ -285,7 +285,7 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { String source = breakpoint.first; int linenr = breakpoint.second; - if (source.empty()) { + if (source.is_empty()) { continue; } @@ -323,7 +323,7 @@ void LocalDebugger::print_variables(const List<String> &names, const List<Varian for (const List<String>::Element *E = names.front(); E; E = E->next()) { value = String(V->get()); - if (variable_prefix.empty()) { + if (variable_prefix.is_empty()) { print_line(E->get() + ": " + String(V->get())); } else { print_line(E->get() + ":"); @@ -359,7 +359,7 @@ void LocalDebugger::send_message(const String &p_message, const Array &p_args) { } void LocalDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) { - print_line("ERROR: '" + (p_descr.empty() ? p_err : p_descr) + "'"); + print_line("ERROR: '" + (p_descr.is_empty() ? p_err : p_descr) + "'"); } LocalDebugger::LocalDebugger() { diff --git a/core/debugger/local_debugger.h b/core/debugger/local_debugger.h index d342da6d44..e793b2a859 100644 --- a/core/debugger/local_debugger.h +++ b/core/debugger/local_debugger.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,8 +32,8 @@ #define LOCAL_DEBUGGER_H #include "core/debugger/engine_debugger.h" -#include "core/list.h" -#include "core/script_language.h" +#include "core/object/script_language.h" +#include "core/templates/list.h" class LocalDebugger : public EngineDebugger { private: diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index 9d55e1312e..7392e6b9a6 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,13 +30,13 @@ #include "remote_debugger.h" +#include "core/config/project_settings.h" #include "core/debugger/debugger_marshalls.h" #include "core/debugger/engine_debugger.h" #include "core/debugger/script_debugger.h" #include "core/input/input.h" +#include "core/object/script_language.h" #include "core/os/os.h" -#include "core/project_settings.h" -#include "core/script_language.h" #include "scene/main/node.h" #include "servers/display_server.h" @@ -317,7 +317,7 @@ struct RemoteDebugger::ServersProfiler { void _send_frame_data(bool p_final) { DebuggerMarshalls::ServersProfilerFrame frame; - frame.frame_number = Engine::get_singleton()->get_idle_frames(); + frame.frame_number = Engine::get_singleton()->get_process_frames(); frame.frame_time = frame_time; frame.idle_time = idle_time; frame.physics_time = physics_time; @@ -553,7 +553,7 @@ void RemoteDebugger::flush_output() { for (int i = 0; i < output_strings.size(); i++) { const OutputString &output_string = output_strings[i]; if (output_string.type == MESSAGE_TYPE_ERROR) { - if (!joined_log_strings.empty()) { + if (!joined_log_strings.is_empty()) { strings.push_back(String("\n").join(joined_log_strings)); types.push_back(MESSAGE_TYPE_LOG); joined_log_strings.clear(); @@ -565,7 +565,7 @@ void RemoteDebugger::flush_output() { } } - if (!joined_log_strings.empty()) { + if (!joined_log_strings.is_empty()) { strings.push_back(String("\n").join(joined_log_strings)); types.push_back(MESSAGE_TYPE_LOG); } diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h index dc7e4436e1..28e670747e 100644 --- a/core/debugger/remote_debugger.h +++ b/core/debugger/remote_debugger.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,13 +31,13 @@ #ifndef REMOTE_DEBUGGER_H #define REMOTE_DEBUGGER_H -#include "core/array.h" #include "core/debugger/debugger_marshalls.h" #include "core/debugger/engine_debugger.h" #include "core/debugger/remote_debugger_peer.h" -#include "core/object.h" -#include "core/string_name.h" -#include "core/ustring.h" +#include "core/object/class_db.h" +#include "core/string/string_name.h" +#include "core/string/ustring.h" +#include "core/variant/array.h" class RemoteDebugger : public EngineDebugger { public: diff --git a/core/debugger/remote_debugger_peer.cpp b/core/debugger/remote_debugger_peer.cpp index 0ce0042f50..2e388d5934 100644 --- a/core/debugger/remote_debugger_peer.cpp +++ b/core/debugger/remote_debugger_peer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,9 @@ #include "remote_debugger_peer.h" +#include "core/config/project_settings.h" #include "core/io/marshalls.h" #include "core/os/os.h" -#include "core/project_settings.h" bool RemoteDebuggerPeerTCP::is_peer_connected() { return connected; diff --git a/core/debugger/remote_debugger_peer.h b/core/debugger/remote_debugger_peer.h index 3a75a2a02b..c759c65568 100644 --- a/core/debugger/remote_debugger_peer.h +++ b/core/debugger/remote_debugger_peer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,10 +32,10 @@ #define REMOTE_DEBUGGER_PEER_H #include "core/io/stream_peer_tcp.h" +#include "core/object/reference.h" #include "core/os/mutex.h" #include "core/os/thread.h" -#include "core/reference.h" -#include "core/ustring.h" +#include "core/string/ustring.h" class RemoteDebuggerPeer : public Reference { protected: diff --git a/core/debugger/script_debugger.cpp b/core/debugger/script_debugger.cpp index 0cd3238efb..6d1e4ed101 100644 --- a/core/debugger/script_debugger.cpp +++ b/core/debugger/script_debugger.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/debugger/script_debugger.h b/core/debugger/script_debugger.h index 0068691825..9f034a5e5d 100644 --- a/core/debugger/script_debugger.h +++ b/core/debugger/script_debugger.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,11 +31,11 @@ #ifndef SCRIPT_DEBUGGER_H #define SCRIPT_DEBUGGER_H -#include "core/map.h" -#include "core/script_language.h" -#include "core/set.h" -#include "core/string_name.h" -#include "core/vector.h" +#include "core/object/script_language.h" +#include "core/string/string_name.h" +#include "core/templates/map.h" +#include "core/templates/set.h" +#include "core/templates/vector.h" class ScriptDebugger { typedef ScriptLanguage::StackInfo StackInfo; diff --git a/core/doc_data.cpp b/core/doc_data.cpp new file mode 100644 index 0000000000..45450bf97a --- /dev/null +++ b/core/doc_data.cpp @@ -0,0 +1,126 @@ +/*************************************************************************/ +/* doc_data.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "doc_data.h" + +void DocData::return_doc_from_retinfo(DocData::MethodDoc &p_method, const PropertyInfo &p_retinfo) { + if (p_retinfo.type == Variant::INT && p_retinfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + p_method.return_enum = p_retinfo.class_name; + if (p_method.return_enum.begins_with("_")) { //proxy class + p_method.return_enum = p_method.return_enum.substr(1, p_method.return_enum.length()); + } + p_method.return_type = "int"; + } else if (p_retinfo.class_name != StringName()) { + p_method.return_type = p_retinfo.class_name; + } else if (p_retinfo.type == Variant::ARRAY && p_retinfo.hint == PROPERTY_HINT_ARRAY_TYPE) { + p_method.return_type = p_retinfo.hint_string + "[]"; + } else if (p_retinfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { + p_method.return_type = p_retinfo.hint_string; + } else if (p_retinfo.type == Variant::NIL && p_retinfo.usage & PROPERTY_USAGE_NIL_IS_VARIANT) { + p_method.return_type = "Variant"; + } else if (p_retinfo.type == Variant::NIL) { + p_method.return_type = "void"; + } else { + p_method.return_type = Variant::get_type_name(p_retinfo.type); + } +} + +void DocData::argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const PropertyInfo &p_arginfo) { + p_argument.name = p_arginfo.name; + + if (p_arginfo.type == Variant::INT && p_arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + p_argument.enumeration = p_arginfo.class_name; + if (p_argument.enumeration.begins_with("_")) { //proxy class + p_argument.enumeration = p_argument.enumeration.substr(1, p_argument.enumeration.length()); + } + p_argument.type = "int"; + } else if (p_arginfo.class_name != StringName()) { + p_argument.type = p_arginfo.class_name; + } else if (p_arginfo.type == Variant::ARRAY && p_arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) { + p_argument.type = p_arginfo.hint_string + "[]"; + } else if (p_arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) { + p_argument.type = p_arginfo.hint_string; + } else if (p_arginfo.type == Variant::NIL) { + // Parameters cannot be void, so PROPERTY_USAGE_NIL_IS_VARIANT is not necessary + p_argument.type = "Variant"; + } else { + p_argument.type = Variant::get_type_name(p_arginfo.type); + } +} + +void DocData::property_doc_from_scriptmemberinfo(DocData::PropertyDoc &p_property, const ScriptMemberInfo &p_memberinfo) { + p_property.name = p_memberinfo.propinfo.name; + p_property.description = p_memberinfo.doc_string; + + if (p_memberinfo.propinfo.type == Variant::OBJECT) { + p_property.type = p_memberinfo.propinfo.class_name; + } else if (p_memberinfo.propinfo.type == Variant::NIL && p_memberinfo.propinfo.usage & PROPERTY_USAGE_NIL_IS_VARIANT) { + p_property.type = "Variant"; + } else { + p_property.type = Variant::get_type_name(p_memberinfo.propinfo.type); + } + + p_property.setter = p_memberinfo.setter; + p_property.getter = p_memberinfo.getter; + + if (p_memberinfo.has_default_value && p_memberinfo.default_value.get_type() != Variant::OBJECT) { + p_property.default_value = p_memberinfo.default_value.get_construct_string().replace("\n", ""); + } + + p_property.overridden = false; +} + +void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const MethodInfo &p_methodinfo, const String &p_desc) { + p_method.name = p_methodinfo.name; + p_method.description = p_desc; + + return_doc_from_retinfo(p_method, p_methodinfo.return_val); + + for (int i = 0; i < p_methodinfo.arguments.size(); i++) { + DocData::ArgumentDoc argument; + argument_doc_from_arginfo(argument, p_methodinfo.arguments[i]); + int default_arg_index = i - (p_methodinfo.arguments.size() - p_methodinfo.default_arguments.size()); + if (default_arg_index >= 0) { + Variant default_arg = p_methodinfo.default_arguments[default_arg_index]; + argument.default_value = default_arg.get_construct_string(); + } + p_method.arguments.push_back(argument); + } +} + +void DocData::constant_doc_from_variant(DocData::ConstantDoc &p_const, const StringName &p_name, const Variant &p_value, const String &p_desc) { + p_const.name = p_name; + p_const.value = p_value; + p_const.description = p_desc; +} + +void DocData::signal_doc_from_methodinfo(DocData::MethodDoc &p_signal, const MethodInfo &p_methodinfo, const String &p_desc) { + return method_doc_from_methodinfo(p_signal, p_methodinfo, p_desc); +} diff --git a/core/doc_data.h b/core/doc_data.h new file mode 100644 index 0000000000..46ab697768 --- /dev/null +++ b/core/doc_data.h @@ -0,0 +1,152 @@ +/*************************************************************************/ +/* doc_data.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef DOC_DATA_H +#define DOC_DATA_H + +#include "core/io/xml_parser.h" +#include "core/templates/map.h" +#include "core/variant/variant.h" + +struct ScriptMemberInfo { + PropertyInfo propinfo; + String doc_string; + StringName setter; + StringName getter; + + bool has_default_value = false; + Variant default_value; +}; + +class DocData { +public: + struct ArgumentDoc { + String name; + String type; + String enumeration; + String default_value; + bool operator<(const ArgumentDoc &p_arg) const { + if (name == p_arg.name) { + return type < p_arg.type; + } + return name < p_arg.name; + } + }; + + struct MethodDoc { + String name; + String return_type; + String return_enum; + String qualifiers; + String description; + Vector<ArgumentDoc> arguments; + bool operator<(const MethodDoc &p_method) const { + if (name == p_method.name) { + // Must be a constructor since there is no overloading. + // We want this arbitrary order for a class "Foo": + // - 1. Default constructor: Foo() + // - 2. Copy constructor: Foo(Foo) + // - 3+. Other constructors Foo(Bar, ...) based on first argument's name + if (arguments.size() == 0 || p_method.arguments.size() == 0) { // 1. + return arguments.size() < p_method.arguments.size(); + } + if (arguments[0].type == return_type || p_method.arguments[0].type == p_method.return_type) { // 2. + return (arguments[0].type == return_type) || (p_method.arguments[0].type != p_method.return_type); + } + return arguments[0] < p_method.arguments[0]; + } + return name < p_method.name; + } + }; + + struct ConstantDoc { + String name; + String value; + bool is_value_valid = false; + String enumeration; + String description; + bool operator<(const ConstantDoc &p_const) const { + return name < p_const.name; + } + }; + + struct EnumDoc { + String name = "@unnamed_enum"; + String description; + Vector<DocData::ConstantDoc> values; + }; + + struct PropertyDoc { + String name; + String type; + String enumeration; + String description; + String setter, getter; + String default_value; + bool overridden = false; + bool operator<(const PropertyDoc &p_prop) const { + return name < p_prop.name; + } + }; + + struct TutorialDoc { + String link; + String title; + }; + + struct ClassDoc { + String name; + String inherits; + String category; + String brief_description; + String description; + Vector<TutorialDoc> tutorials; + Vector<MethodDoc> methods; + Vector<MethodDoc> signals; + Vector<ConstantDoc> constants; + Map<String, String> enums; + Vector<PropertyDoc> properties; + Vector<PropertyDoc> theme_properties; + bool is_script_doc = false; + String script_path; + bool operator<(const ClassDoc &p_class) const { + return name < p_class.name; + } + }; + + static void return_doc_from_retinfo(DocData::MethodDoc &p_method, const PropertyInfo &p_retinfo); + static void argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const PropertyInfo &p_arginfo); + static void property_doc_from_scriptmemberinfo(DocData::PropertyDoc &p_property, const ScriptMemberInfo &p_memberinfo); + static void method_doc_from_methodinfo(DocData::MethodDoc &p_method, const MethodInfo &p_methodinfo, const String &p_desc); + static void constant_doc_from_variant(DocData::ConstantDoc &p_const, const StringName &p_name, const Variant &p_value, const String &p_desc); + static void signal_doc_from_methodinfo(DocData::MethodDoc &p_signal, const MethodInfo &p_methodinfo, const String &p_desc); +}; + +#endif // DOC_DATA_H diff --git a/core/error/SCsub b/core/error/SCsub new file mode 100644 index 0000000000..dfd6248a94 --- /dev/null +++ b/core/error/SCsub @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +Import("env") + +env_error = env.Clone() + +env_error.add_source_files(env.core_sources, "*.cpp") diff --git a/core/error_list.h b/core/error/error_list.h index a0218cf045..f032f44c1f 100644 --- a/core/error_list.h +++ b/core/error/error_list.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/error_macros.cpp b/core/error/error_macros.cpp index 2fae939965..272dda97d8 100644 --- a/core/error_macros.cpp +++ b/core/error/error_macros.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #include "error_macros.h" #include "core/io/logger.h" -#include "core/ustring.h" -#include "os/os.h" +#include "core/os/os.h" +#include "core/string/ustring.h" static ErrorHandlerList *error_handler_list = nullptr; diff --git a/core/error_macros.h b/core/error/error_macros.h index 6353961b04..8eb6217ce8 100644 --- a/core/error_macros.h +++ b/core/error/error_macros.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/func_ref.cpp b/core/func_ref.cpp deleted file mode 100644 index 7e062f16d0..0000000000 --- a/core/func_ref.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/*************************************************************************/ -/* func_ref.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "func_ref.h" - -Variant FuncRef::call_func(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - if (id.is_null()) { - r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; - return Variant(); - } - Object *obj = ObjectDB::get_instance(id); - - if (!obj) { - r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; - return Variant(); - } - - return obj->call(function, p_args, p_argcount, r_error); -} - -Variant FuncRef::call_funcv(const Array &p_args) { - ERR_FAIL_COND_V(id.is_null(), Variant()); - - Object *obj = ObjectDB::get_instance(id); - - ERR_FAIL_COND_V(!obj, Variant()); - - return obj->callv(function, p_args); -} - -void FuncRef::set_instance(Object *p_obj) { - ERR_FAIL_NULL(p_obj); - id = p_obj->get_instance_id(); -} - -void FuncRef::set_function(const StringName &p_func) { - function = p_func; -} - -StringName FuncRef::get_function() { - return function; -} - -bool FuncRef::is_valid() const { - if (id.is_null()) { - return false; - } - - Object *obj = ObjectDB::get_instance(id); - if (!obj) { - return false; - } - - return obj->has_method(function); -} - -void FuncRef::_bind_methods() { - { - MethodInfo mi; - mi.name = "call_func"; - Vector<Variant> defargs; - ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "call_func", &FuncRef::call_func, mi, defargs); - } - - ClassDB::bind_method(D_METHOD("call_funcv", "arg_array"), &FuncRef::call_funcv); - - ClassDB::bind_method(D_METHOD("set_instance", "instance"), &FuncRef::set_instance); - ClassDB::bind_method(D_METHOD("is_valid"), &FuncRef::is_valid); - - ClassDB::bind_method(D_METHOD("set_function", "name"), &FuncRef::set_function); - ClassDB::bind_method(D_METHOD("get_function"), &FuncRef::get_function); - - ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "function"), "set_function", "get_function"); -} diff --git a/core/func_ref.h b/core/func_ref.h deleted file mode 100644 index 75b84e705e..0000000000 --- a/core/func_ref.h +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************/ -/* func_ref.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef FUNC_REF_H -#define FUNC_REF_H - -#include "core/reference.h" - -class FuncRef : public Reference { - GDCLASS(FuncRef, Reference); - ObjectID id; - StringName function; - -protected: - static void _bind_methods(); - -public: - Variant call_func(const Variant **p_args, int p_argcount, Callable::CallError &r_error); - Variant call_funcv(const Array &p_args); - void set_instance(Object *p_obj); - void set_function(const StringName &p_func); - StringName get_function(); - bool is_valid() const; - - FuncRef() {} -}; - -#endif // FUNC_REF_H diff --git a/core/global_constants.cpp b/core/global_constants.cpp deleted file mode 100644 index b30685539a..0000000000 --- a/core/global_constants.cpp +++ /dev/null @@ -1,691 +0,0 @@ -/*************************************************************************/ -/* global_constants.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "global_constants.h" - -#include "core/input/input_event.h" -#include "core/object.h" -#include "core/os/keyboard.h" -#include "core/variant.h" - -struct _GlobalConstant { -#ifdef DEBUG_METHODS_ENABLED - StringName enum_name; - bool ignore_value_in_docs; -#endif - const char *name; - int value; - - _GlobalConstant() {} - -#ifdef DEBUG_METHODS_ENABLED - _GlobalConstant(const StringName &p_enum_name, const char *p_name, int p_value, bool p_ignore_value_in_docs = false) : - enum_name(p_enum_name), - ignore_value_in_docs(p_ignore_value_in_docs), - name(p_name), - value(p_value) { - } -#else - _GlobalConstant(const char *p_name, int p_value) : - name(p_name), - value(p_value) { - } -#endif -}; - -static Vector<_GlobalConstant> _global_constants; - -#ifdef DEBUG_METHODS_ENABLED - -#define BIND_GLOBAL_CONSTANT(m_constant) \ - _global_constants.push_back(_GlobalConstant(StringName(), #m_constant, m_constant)); - -#define BIND_GLOBAL_ENUM_CONSTANT(m_constant) \ - _global_constants.push_back(_GlobalConstant(__constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant)); - -#define BIND_GLOBAL_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \ - _global_constants.push_back(_GlobalConstant(__constant_get_enum_name(m_constant, #m_constant), m_custom_name, m_constant)); - -#define BIND_GLOBAL_CONSTANT_NO_VAL(m_constant) \ - _global_constants.push_back(_GlobalConstant(StringName(), #m_constant, m_constant, true)); - -#define BIND_GLOBAL_ENUM_CONSTANT_NO_VAL(m_constant) \ - _global_constants.push_back(_GlobalConstant(__constant_get_enum_name(m_constant, #m_constant), #m_constant, m_constant, true)); - -#define BIND_GLOBAL_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \ - _global_constants.push_back(_GlobalConstant(__constant_get_enum_name(m_constant, #m_constant), m_custom_name, m_constant, true)); - -#else - -#define BIND_GLOBAL_CONSTANT(m_constant) \ - _global_constants.push_back(_GlobalConstant(#m_constant, m_constant)); - -#define BIND_GLOBAL_ENUM_CONSTANT(m_constant) \ - _global_constants.push_back(_GlobalConstant(#m_constant, m_constant)); - -#define BIND_GLOBAL_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \ - _global_constants.push_back(_GlobalConstant(m_custom_name, m_constant)); - -#define BIND_GLOBAL_CONSTANT_NO_VAL(m_constant) \ - _global_constants.push_back(_GlobalConstant(#m_constant, m_constant)); - -#define BIND_GLOBAL_ENUM_CONSTANT_NO_VAL(m_constant) \ - _global_constants.push_back(_GlobalConstant(#m_constant, m_constant)); - -#define BIND_GLOBAL_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \ - _global_constants.push_back(_GlobalConstant(m_custom_name, m_constant)); - -#endif - -VARIANT_ENUM_CAST(KeyList); -VARIANT_ENUM_CAST(KeyModifierMask); -VARIANT_ENUM_CAST(ButtonList); -VARIANT_ENUM_CAST(JoyButtonList); -VARIANT_ENUM_CAST(JoyAxisList); -VARIANT_ENUM_CAST(MidiMessageList); - -void register_global_constants() { - BIND_GLOBAL_ENUM_CONSTANT(MARGIN_LEFT); - BIND_GLOBAL_ENUM_CONSTANT(MARGIN_TOP); - BIND_GLOBAL_ENUM_CONSTANT(MARGIN_RIGHT); - BIND_GLOBAL_ENUM_CONSTANT(MARGIN_BOTTOM); - - BIND_GLOBAL_ENUM_CONSTANT(CORNER_TOP_LEFT); - BIND_GLOBAL_ENUM_CONSTANT(CORNER_TOP_RIGHT); - BIND_GLOBAL_ENUM_CONSTANT(CORNER_BOTTOM_RIGHT); - BIND_GLOBAL_ENUM_CONSTANT(CORNER_BOTTOM_LEFT); - - BIND_GLOBAL_ENUM_CONSTANT(VERTICAL); - BIND_GLOBAL_ENUM_CONSTANT(HORIZONTAL); - - BIND_GLOBAL_ENUM_CONSTANT(HALIGN_LEFT); - BIND_GLOBAL_ENUM_CONSTANT(HALIGN_CENTER); - BIND_GLOBAL_ENUM_CONSTANT(HALIGN_RIGHT); - - BIND_GLOBAL_ENUM_CONSTANT(VALIGN_TOP); - BIND_GLOBAL_ENUM_CONSTANT(VALIGN_CENTER); - BIND_GLOBAL_ENUM_CONSTANT(VALIGN_BOTTOM); - - // huge list of keys - BIND_GLOBAL_CONSTANT(SPKEY); - - BIND_GLOBAL_ENUM_CONSTANT(KEY_ESCAPE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_TAB); - BIND_GLOBAL_ENUM_CONSTANT(KEY_BACKTAB); - BIND_GLOBAL_ENUM_CONSTANT(KEY_BACKSPACE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ENTER); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_ENTER); - BIND_GLOBAL_ENUM_CONSTANT(KEY_INSERT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_DELETE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_PAUSE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_PRINT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_SYSREQ); - BIND_GLOBAL_ENUM_CONSTANT(KEY_CLEAR); - BIND_GLOBAL_ENUM_CONSTANT(KEY_HOME); - BIND_GLOBAL_ENUM_CONSTANT(KEY_END); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LEFT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_UP); - BIND_GLOBAL_ENUM_CONSTANT(KEY_RIGHT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_DOWN); - BIND_GLOBAL_ENUM_CONSTANT(KEY_PAGEUP); - BIND_GLOBAL_ENUM_CONSTANT(KEY_PAGEDOWN); - BIND_GLOBAL_ENUM_CONSTANT(KEY_SHIFT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_CONTROL); - BIND_GLOBAL_ENUM_CONSTANT(KEY_META); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ALT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_CAPSLOCK); - BIND_GLOBAL_ENUM_CONSTANT(KEY_NUMLOCK); - BIND_GLOBAL_ENUM_CONSTANT(KEY_SCROLLLOCK); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F1); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F2); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F3); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F4); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F5); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F6); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F7); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F8); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F9); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F10); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F11); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F12); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F13); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F14); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F15); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F16); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_MULTIPLY); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_DIVIDE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_SUBTRACT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_PERIOD); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_ADD); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_0); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_1); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_2); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_3); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_4); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_5); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_6); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_7); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_8); - BIND_GLOBAL_ENUM_CONSTANT(KEY_KP_9); - BIND_GLOBAL_ENUM_CONSTANT(KEY_SUPER_L); - BIND_GLOBAL_ENUM_CONSTANT(KEY_SUPER_R); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MENU); - BIND_GLOBAL_ENUM_CONSTANT(KEY_HYPER_L); - BIND_GLOBAL_ENUM_CONSTANT(KEY_HYPER_R); - BIND_GLOBAL_ENUM_CONSTANT(KEY_HELP); - BIND_GLOBAL_ENUM_CONSTANT(KEY_DIRECTION_L); - BIND_GLOBAL_ENUM_CONSTANT(KEY_DIRECTION_R); - BIND_GLOBAL_ENUM_CONSTANT(KEY_BACK); - BIND_GLOBAL_ENUM_CONSTANT(KEY_FORWARD); - BIND_GLOBAL_ENUM_CONSTANT(KEY_STOP); - BIND_GLOBAL_ENUM_CONSTANT(KEY_REFRESH); - BIND_GLOBAL_ENUM_CONSTANT(KEY_VOLUMEDOWN); - BIND_GLOBAL_ENUM_CONSTANT(KEY_VOLUMEMUTE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_VOLUMEUP); - BIND_GLOBAL_ENUM_CONSTANT(KEY_BASSBOOST); - BIND_GLOBAL_ENUM_CONSTANT(KEY_BASSUP); - BIND_GLOBAL_ENUM_CONSTANT(KEY_BASSDOWN); - BIND_GLOBAL_ENUM_CONSTANT(KEY_TREBLEUP); - BIND_GLOBAL_ENUM_CONSTANT(KEY_TREBLEDOWN); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MEDIAPLAY); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MEDIASTOP); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MEDIAPREVIOUS); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MEDIANEXT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MEDIARECORD); - BIND_GLOBAL_ENUM_CONSTANT(KEY_HOMEPAGE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_FAVORITES); - BIND_GLOBAL_ENUM_CONSTANT(KEY_SEARCH); - BIND_GLOBAL_ENUM_CONSTANT(KEY_STANDBY); - BIND_GLOBAL_ENUM_CONSTANT(KEY_OPENURL); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCHMAIL); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCHMEDIA); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCH0); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCH1); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCH2); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCH3); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCH4); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCH5); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCH6); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCH7); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCH8); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCH9); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCHA); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCHB); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCHC); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCHD); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCHE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LAUNCHF); - - BIND_GLOBAL_ENUM_CONSTANT(KEY_UNKNOWN); - BIND_GLOBAL_ENUM_CONSTANT(KEY_SPACE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_EXCLAM); - BIND_GLOBAL_ENUM_CONSTANT(KEY_QUOTEDBL); - BIND_GLOBAL_ENUM_CONSTANT(KEY_NUMBERSIGN); - BIND_GLOBAL_ENUM_CONSTANT(KEY_DOLLAR); - BIND_GLOBAL_ENUM_CONSTANT(KEY_PERCENT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_AMPERSAND); - BIND_GLOBAL_ENUM_CONSTANT(KEY_APOSTROPHE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_PARENLEFT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_PARENRIGHT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ASTERISK); - BIND_GLOBAL_ENUM_CONSTANT(KEY_PLUS); - BIND_GLOBAL_ENUM_CONSTANT(KEY_COMMA); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MINUS); - BIND_GLOBAL_ENUM_CONSTANT(KEY_PERIOD); - BIND_GLOBAL_ENUM_CONSTANT(KEY_SLASH); - BIND_GLOBAL_ENUM_CONSTANT(KEY_0); - BIND_GLOBAL_ENUM_CONSTANT(KEY_1); - BIND_GLOBAL_ENUM_CONSTANT(KEY_2); - BIND_GLOBAL_ENUM_CONSTANT(KEY_3); - BIND_GLOBAL_ENUM_CONSTANT(KEY_4); - BIND_GLOBAL_ENUM_CONSTANT(KEY_5); - BIND_GLOBAL_ENUM_CONSTANT(KEY_6); - BIND_GLOBAL_ENUM_CONSTANT(KEY_7); - BIND_GLOBAL_ENUM_CONSTANT(KEY_8); - BIND_GLOBAL_ENUM_CONSTANT(KEY_9); - BIND_GLOBAL_ENUM_CONSTANT(KEY_COLON); - BIND_GLOBAL_ENUM_CONSTANT(KEY_SEMICOLON); - BIND_GLOBAL_ENUM_CONSTANT(KEY_LESS); - BIND_GLOBAL_ENUM_CONSTANT(KEY_EQUAL); - BIND_GLOBAL_ENUM_CONSTANT(KEY_GREATER); - BIND_GLOBAL_ENUM_CONSTANT(KEY_QUESTION); - BIND_GLOBAL_ENUM_CONSTANT(KEY_AT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_A); - BIND_GLOBAL_ENUM_CONSTANT(KEY_B); - BIND_GLOBAL_ENUM_CONSTANT(KEY_C); - BIND_GLOBAL_ENUM_CONSTANT(KEY_D); - BIND_GLOBAL_ENUM_CONSTANT(KEY_E); - BIND_GLOBAL_ENUM_CONSTANT(KEY_F); - BIND_GLOBAL_ENUM_CONSTANT(KEY_G); - BIND_GLOBAL_ENUM_CONSTANT(KEY_H); - BIND_GLOBAL_ENUM_CONSTANT(KEY_I); - BIND_GLOBAL_ENUM_CONSTANT(KEY_J); - BIND_GLOBAL_ENUM_CONSTANT(KEY_K); - BIND_GLOBAL_ENUM_CONSTANT(KEY_L); - BIND_GLOBAL_ENUM_CONSTANT(KEY_M); - BIND_GLOBAL_ENUM_CONSTANT(KEY_N); - BIND_GLOBAL_ENUM_CONSTANT(KEY_O); - BIND_GLOBAL_ENUM_CONSTANT(KEY_P); - BIND_GLOBAL_ENUM_CONSTANT(KEY_Q); - BIND_GLOBAL_ENUM_CONSTANT(KEY_R); - BIND_GLOBAL_ENUM_CONSTANT(KEY_S); - BIND_GLOBAL_ENUM_CONSTANT(KEY_T); - BIND_GLOBAL_ENUM_CONSTANT(KEY_U); - BIND_GLOBAL_ENUM_CONSTANT(KEY_V); - BIND_GLOBAL_ENUM_CONSTANT(KEY_W); - BIND_GLOBAL_ENUM_CONSTANT(KEY_X); - BIND_GLOBAL_ENUM_CONSTANT(KEY_Y); - BIND_GLOBAL_ENUM_CONSTANT(KEY_Z); - BIND_GLOBAL_ENUM_CONSTANT(KEY_BRACKETLEFT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_BACKSLASH); - BIND_GLOBAL_ENUM_CONSTANT(KEY_BRACKETRIGHT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ASCIICIRCUM); - BIND_GLOBAL_ENUM_CONSTANT(KEY_UNDERSCORE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_QUOTELEFT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_BRACELEFT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_BAR); - BIND_GLOBAL_ENUM_CONSTANT(KEY_BRACERIGHT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ASCIITILDE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_NOBREAKSPACE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_EXCLAMDOWN); - BIND_GLOBAL_ENUM_CONSTANT(KEY_CENT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_STERLING); - BIND_GLOBAL_ENUM_CONSTANT(KEY_CURRENCY); - BIND_GLOBAL_ENUM_CONSTANT(KEY_YEN); - BIND_GLOBAL_ENUM_CONSTANT(KEY_BROKENBAR); - BIND_GLOBAL_ENUM_CONSTANT(KEY_SECTION); - BIND_GLOBAL_ENUM_CONSTANT(KEY_DIAERESIS); - BIND_GLOBAL_ENUM_CONSTANT(KEY_COPYRIGHT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ORDFEMININE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_GUILLEMOTLEFT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_NOTSIGN); - BIND_GLOBAL_ENUM_CONSTANT(KEY_HYPHEN); - BIND_GLOBAL_ENUM_CONSTANT(KEY_REGISTERED); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MACRON); - BIND_GLOBAL_ENUM_CONSTANT(KEY_DEGREE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_PLUSMINUS); - BIND_GLOBAL_ENUM_CONSTANT(KEY_TWOSUPERIOR); - BIND_GLOBAL_ENUM_CONSTANT(KEY_THREESUPERIOR); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ACUTE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MU); - BIND_GLOBAL_ENUM_CONSTANT(KEY_PARAGRAPH); - BIND_GLOBAL_ENUM_CONSTANT(KEY_PERIODCENTERED); - BIND_GLOBAL_ENUM_CONSTANT(KEY_CEDILLA); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ONESUPERIOR); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MASCULINE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_GUILLEMOTRIGHT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ONEQUARTER); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ONEHALF); - BIND_GLOBAL_ENUM_CONSTANT(KEY_THREEQUARTERS); - BIND_GLOBAL_ENUM_CONSTANT(KEY_QUESTIONDOWN); - BIND_GLOBAL_ENUM_CONSTANT(KEY_AGRAVE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_AACUTE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ACIRCUMFLEX); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ATILDE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ADIAERESIS); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ARING); - BIND_GLOBAL_ENUM_CONSTANT(KEY_AE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_CCEDILLA); - BIND_GLOBAL_ENUM_CONSTANT(KEY_EGRAVE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_EACUTE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ECIRCUMFLEX); - BIND_GLOBAL_ENUM_CONSTANT(KEY_EDIAERESIS); - BIND_GLOBAL_ENUM_CONSTANT(KEY_IGRAVE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_IACUTE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ICIRCUMFLEX); - BIND_GLOBAL_ENUM_CONSTANT(KEY_IDIAERESIS); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ETH); - BIND_GLOBAL_ENUM_CONSTANT(KEY_NTILDE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_OGRAVE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_OACUTE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_OCIRCUMFLEX); - BIND_GLOBAL_ENUM_CONSTANT(KEY_OTILDE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_ODIAERESIS); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MULTIPLY); - BIND_GLOBAL_ENUM_CONSTANT(KEY_OOBLIQUE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_UGRAVE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_UACUTE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_UCIRCUMFLEX); - BIND_GLOBAL_ENUM_CONSTANT(KEY_UDIAERESIS); - BIND_GLOBAL_ENUM_CONSTANT(KEY_YACUTE); - BIND_GLOBAL_ENUM_CONSTANT(KEY_THORN); - BIND_GLOBAL_ENUM_CONSTANT(KEY_SSHARP); - - BIND_GLOBAL_ENUM_CONSTANT(KEY_DIVISION); - BIND_GLOBAL_ENUM_CONSTANT(KEY_YDIAERESIS); - - BIND_GLOBAL_ENUM_CONSTANT(KEY_CODE_MASK); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MODIFIER_MASK); - - BIND_GLOBAL_ENUM_CONSTANT(KEY_MASK_SHIFT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MASK_ALT); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MASK_META); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MASK_CTRL); - BIND_GLOBAL_ENUM_CONSTANT_NO_VAL(KEY_MASK_CMD); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MASK_KPAD); - BIND_GLOBAL_ENUM_CONSTANT(KEY_MASK_GROUP_SWITCH); - - // mouse - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_LEFT); - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_RIGHT); - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MIDDLE); - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_XBUTTON1); - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_XBUTTON2); - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_UP); - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_DOWN); - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_LEFT); - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_WHEEL_RIGHT); - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_LEFT); - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_RIGHT); - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_MIDDLE); - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_XBUTTON1); - BIND_GLOBAL_ENUM_CONSTANT(BUTTON_MASK_XBUTTON2); - - // Joypad buttons - BIND_GLOBAL_ENUM_CONSTANT(JOY_INVALID_BUTTON); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_A); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_B); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_X); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_Y); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_BACK); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_GUIDE); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_START); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_LEFT_STICK); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_RIGHT_STICK); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_LEFT_SHOULDER); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_RIGHT_SHOULDER); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_DPAD_UP); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_DPAD_DOWN); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_DPAD_LEFT); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_DPAD_RIGHT); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SDL_BUTTONS); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_X); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_CROSS); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_CIRCLE); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_SQUARE); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_TRIANGLE); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_SELECT); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_START); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_PS); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_L1); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_R1); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_L3); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SONY_R3); - BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_A); - BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_B); - BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_X); - BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_Y); - BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_BACK); - BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_START); - BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_HOME); - BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_LS); - BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_RS); - BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_LB); - BIND_GLOBAL_ENUM_CONSTANT(JOY_XBOX_RB); - BIND_GLOBAL_ENUM_CONSTANT(JOY_BUTTON_MAX); - - // Joypad axes - BIND_GLOBAL_ENUM_CONSTANT(JOY_INVALID_AXIS); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_LEFT_X); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_LEFT_Y); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_RIGHT_X); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_RIGHT_Y); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_TRIGGER_LEFT); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_TRIGGER_RIGHT); - BIND_GLOBAL_ENUM_CONSTANT(JOY_SDL_AXES); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_0_X); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_0_Y); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_1_X); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_1_Y); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_2_X); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_2_Y); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_3_X); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_3_Y); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_4_X); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_4_Y); - BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_MAX); - - // midi - BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_OFF); - BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_ON); - BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_AFTERTOUCH); - BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_CONTROL_CHANGE); - BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_PROGRAM_CHANGE); - BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_CHANNEL_PRESSURE); - BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_PITCH_BEND); - - // error list - - BIND_GLOBAL_ENUM_CONSTANT(OK); // (0) - BIND_GLOBAL_ENUM_CONSTANT(FAILED); - BIND_GLOBAL_ENUM_CONSTANT(ERR_UNAVAILABLE); - BIND_GLOBAL_ENUM_CONSTANT(ERR_UNCONFIGURED); - BIND_GLOBAL_ENUM_CONSTANT(ERR_UNAUTHORIZED); - BIND_GLOBAL_ENUM_CONSTANT(ERR_PARAMETER_RANGE_ERROR); // (5) - BIND_GLOBAL_ENUM_CONSTANT(ERR_OUT_OF_MEMORY); - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_NOT_FOUND); - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_BAD_DRIVE); - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_BAD_PATH); - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_NO_PERMISSION); // (10) - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_ALREADY_IN_USE); - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_CANT_OPEN); - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_CANT_WRITE); - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_CANT_READ); - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_UNRECOGNIZED); // (15) - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_CORRUPT); - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_MISSING_DEPENDENCIES); - BIND_GLOBAL_ENUM_CONSTANT(ERR_FILE_EOF); - BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_OPEN); - BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_CREATE); // (20) - BIND_GLOBAL_ENUM_CONSTANT(ERR_QUERY_FAILED); - BIND_GLOBAL_ENUM_CONSTANT(ERR_ALREADY_IN_USE); - BIND_GLOBAL_ENUM_CONSTANT(ERR_LOCKED); - BIND_GLOBAL_ENUM_CONSTANT(ERR_TIMEOUT); - BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_CONNECT); // (25) - BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_RESOLVE); - BIND_GLOBAL_ENUM_CONSTANT(ERR_CONNECTION_ERROR); - BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_ACQUIRE_RESOURCE); - BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_FORK); - BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_DATA); // (30) - BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_PARAMETER); - BIND_GLOBAL_ENUM_CONSTANT(ERR_ALREADY_EXISTS); - BIND_GLOBAL_ENUM_CONSTANT(ERR_DOES_NOT_EXIST); - BIND_GLOBAL_ENUM_CONSTANT(ERR_DATABASE_CANT_READ); - BIND_GLOBAL_ENUM_CONSTANT(ERR_DATABASE_CANT_WRITE); // (35) - BIND_GLOBAL_ENUM_CONSTANT(ERR_COMPILATION_FAILED); - BIND_GLOBAL_ENUM_CONSTANT(ERR_METHOD_NOT_FOUND); - BIND_GLOBAL_ENUM_CONSTANT(ERR_LINK_FAILED); - BIND_GLOBAL_ENUM_CONSTANT(ERR_SCRIPT_FAILED); - BIND_GLOBAL_ENUM_CONSTANT(ERR_CYCLIC_LINK); // (40) - BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_DECLARATION); - BIND_GLOBAL_ENUM_CONSTANT(ERR_DUPLICATE_SYMBOL); - BIND_GLOBAL_ENUM_CONSTANT(ERR_PARSE_ERROR); - BIND_GLOBAL_ENUM_CONSTANT(ERR_BUSY); - BIND_GLOBAL_ENUM_CONSTANT(ERR_SKIP); // (45) - BIND_GLOBAL_ENUM_CONSTANT(ERR_HELP); - BIND_GLOBAL_ENUM_CONSTANT(ERR_BUG); - BIND_GLOBAL_ENUM_CONSTANT(ERR_PRINTER_ON_FIRE); - - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_NONE); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_RANGE); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_EXP_RANGE); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_ENUM); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_EXP_EASING); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_LENGTH); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_KEY_ACCEL); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_FLAGS); - - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_RENDER); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_2D_PHYSICS); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_RENDER); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_LAYERS_3D_PHYSICS); - - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_FILE); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_DIR); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_GLOBAL_FILE); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_GLOBAL_DIR); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_RESOURCE_TYPE); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_MULTILINE_TEXT); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_PLACEHOLDER_TEXT); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_COLOR_NO_ALPHA); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSY); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS); - - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_STORAGE); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_NETWORK); - - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_EDITOR_HELPER); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_CHECKABLE); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_CHECKED); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_INTERNATIONALIZED); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_GROUP); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_CATEGORY); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_SUBGROUP); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_NO_INSTANCE_STATE); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_RESTART_IF_CHANGED); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_SCRIPT_VARIABLE); - - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_DEFAULT_INTL); - BIND_GLOBAL_ENUM_CONSTANT(PROPERTY_USAGE_NOEDITOR); - - BIND_GLOBAL_ENUM_CONSTANT(METHOD_FLAG_NORMAL); - BIND_GLOBAL_ENUM_CONSTANT(METHOD_FLAG_EDITOR); - BIND_GLOBAL_ENUM_CONSTANT(METHOD_FLAG_NOSCRIPT); - BIND_GLOBAL_ENUM_CONSTANT(METHOD_FLAG_CONST); - BIND_GLOBAL_ENUM_CONSTANT(METHOD_FLAG_REVERSE); - BIND_GLOBAL_ENUM_CONSTANT(METHOD_FLAG_VIRTUAL); - BIND_GLOBAL_ENUM_CONSTANT(METHOD_FLAG_FROM_SCRIPT); - BIND_GLOBAL_ENUM_CONSTANT(METHOD_FLAGS_DEFAULT); - - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_BOOL", Variant::BOOL); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_INT", Variant::INT); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_REAL", Variant::FLOAT); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_STRING", Variant::STRING); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR2", Variant::VECTOR2); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR2I", Variant::VECTOR2I); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_RECT2", Variant::RECT2); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_RECT2I", Variant::RECT2I); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3", Variant::VECTOR3); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3I", Variant::VECTOR3I); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM2D", Variant::TRANSFORM2D); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_PLANE", Variant::PLANE); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_QUAT", Variant::QUAT); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_AABB", Variant::AABB); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_BASIS", Variant::BASIS); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_TRANSFORM", Variant::TRANSFORM); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_COLOR", Variant::COLOR); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_STRING_NAME", Variant::STRING_NAME); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_NODE_PATH", Variant::NODE_PATH); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_RID", Variant::_RID); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_OBJECT", Variant::OBJECT); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_CALLABLE", Variant::CALLABLE); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_SIGNAL", Variant::SIGNAL); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_DICTIONARY", Variant::DICTIONARY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_ARRAY", Variant::ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_RAW_ARRAY", Variant::PACKED_BYTE_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_INT32_ARRAY", Variant::PACKED_INT32_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_INT64_ARRAY", Variant::PACKED_INT64_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_FLOAT32_ARRAY", Variant::PACKED_FLOAT32_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_FLOAT64_ARRAY", Variant::PACKED_FLOAT64_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_STRING_ARRAY", Variant::PACKED_STRING_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR2_ARRAY", Variant::PACKED_VECTOR2_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_VECTOR3_ARRAY", Variant::PACKED_VECTOR3_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_COLOR_ARRAY", Variant::PACKED_COLOR_ARRAY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("TYPE_MAX", Variant::VARIANT_MAX); - - //comparison - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_EQUAL", Variant::OP_EQUAL); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_NOT_EQUAL", Variant::OP_NOT_EQUAL); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_LESS", Variant::OP_LESS); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_LESS_EQUAL", Variant::OP_LESS_EQUAL); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_GREATER", Variant::OP_GREATER); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_GREATER_EQUAL", Variant::OP_GREATER_EQUAL); - //mathematic - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_ADD", Variant::OP_ADD); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_SUBTRACT", Variant::OP_SUBTRACT); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_MULTIPLY", Variant::OP_MULTIPLY); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_DIVIDE", Variant::OP_DIVIDE); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_NEGATE", Variant::OP_NEGATE); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_POSITIVE", Variant::OP_POSITIVE); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_MODULE", Variant::OP_MODULE); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_STRING_CONCAT", Variant::OP_STRING_CONCAT); - //bitwise - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_SHIFT_LEFT", Variant::OP_SHIFT_LEFT); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_SHIFT_RIGHT", Variant::OP_SHIFT_RIGHT); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_BIT_AND", Variant::OP_BIT_AND); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_BIT_OR", Variant::OP_BIT_OR); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_BIT_XOR", Variant::OP_BIT_XOR); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_BIT_NEGATE", Variant::OP_BIT_NEGATE); - //logic - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_AND", Variant::OP_AND); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_OR", Variant::OP_OR); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_XOR", Variant::OP_XOR); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_NOT", Variant::OP_NOT); - //containment - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_IN", Variant::OP_IN); - BIND_GLOBAL_ENUM_CONSTANT_CUSTOM("OP_MAX", Variant::OP_MAX); -} - -void unregister_global_constants() { - _global_constants.clear(); -} - -int GlobalConstants::get_global_constant_count() { - return _global_constants.size(); -} - -#ifdef DEBUG_METHODS_ENABLED -StringName GlobalConstants::get_global_constant_enum(int p_idx) { - return _global_constants[p_idx].enum_name; -} - -bool GlobalConstants::get_ignore_value_in_docs(int p_idx) { - return _global_constants[p_idx].ignore_value_in_docs; -} -#else -StringName GlobalConstants::get_global_constant_enum(int p_idx) { - return StringName(); -} - -bool GlobalConstants::get_ignore_value_in_docs(int p_idx) { - return false; -} -#endif - -const char *GlobalConstants::get_global_constant_name(int p_idx) { - return _global_constants[p_idx].name; -} - -int GlobalConstants::get_global_constant_value(int p_idx) { - return _global_constants[p_idx].value; -} diff --git a/core/input/default_controller_mappings.h b/core/input/default_controller_mappings.h index 9e2a69acec..ba5e650226 100644 --- a/core/input/default_controller_mappings.h +++ b/core/input/default_controller_mappings.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/input/gamecontrollerdb.txt b/core/input/gamecontrollerdb.txt index 2a3cb23202..180708cea6 100644 --- a/core/input/gamecontrollerdb.txt +++ b/core/input/gamecontrollerdb.txt @@ -338,7 +338,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2, 03000000120c0000101e000000000000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows, # Mac OS X -030000008f0e00000300000009010000,2In1 USB Joystick,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +030000008f0e00000300000009010000,2In1 USB Joystick,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X, 03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, 03000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Mac OS X, diff --git a/core/input/input.cpp b/core/input/input.cpp index 4d152c1ac4..c96884a7b3 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,16 +30,16 @@ #include "input.h" +#include "core/config/project_settings.h" #include "core/input/default_controller_mappings.h" #include "core/input/input_map.h" #include "core/os/os.h" -#include "core/project_settings.h" #ifdef TOOLS_ENABLED #include "editor/editor_settings.h" #endif -static const char *_joy_buttons[JOY_SDL_BUTTONS + 1] = { +static const char *_joy_buttons[JOY_BUTTON_SDL_MAX] = { "a", "b", "x", @@ -55,69 +55,15 @@ static const char *_joy_buttons[JOY_SDL_BUTTONS + 1] = { "dpdown", "dpleft", "dpright", - nullptr }; -static const char *_joy_button_names[JOY_BUTTON_MAX] = { - "Face Bottom", - "Face Right", - "Face Left", - "Face Top", - "Select", - "Guide", - "Start", - "Left Stick", - "Right Stick", - "Left Shoulder", - "Right Shoulder", - "D-Pad Up", - "D-Pad Down", - "D-Pad Left", - "D-Pad Right", - "Button 15", - "Button 16", - "Button 17", - "Button 18", - "Button 19", - "Button 20", - "Button 21", - "Button 22", - "Button 23", - "Button 24", - "Button 25", - "Button 26", - "Button 27", - "Button 28", - "Button 29", - "Button 30", - "Button 31", - "Button 32", - "Button 33", - "Button 34", - "Button 35" -}; - -static const char *_joy_axes[JOY_SDL_AXES + 1] = { +static const char *_joy_axes[JOY_AXIS_SDL_MAX] = { "leftx", "lefty", "rightx", "righty", "lefttrigger", "righttrigger", - nullptr -}; - -static const char *_joy_axis_names[JOY_AXIS_MAX] = { - "Left Stick X", - "Left Stick Y", - "Right Stick X", - "Right Stick Y", - "Left Trigger", - "Right Trigger", - "Joystick 3 Stick X", - "Joystick 3 Stick Y", - "Joystick 4 Stick X", - "Joystick 4 Stick Y" }; Input *Input::singleton = nullptr; @@ -149,6 +95,9 @@ void Input::_bind_methods() { ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action"), &Input::is_action_just_pressed); ClassDB::bind_method(D_METHOD("is_action_just_released", "action"), &Input::is_action_just_released); ClassDB::bind_method(D_METHOD("get_action_strength", "action"), &Input::get_action_strength); + ClassDB::bind_method(D_METHOD("get_action_raw_strength", "action"), &Input::get_action_strength); + ClassDB::bind_method(D_METHOD("get_axis", "negative_action", "positive_action"), &Input::get_axis); + ClassDB::bind_method(D_METHOD("get_vector", "negative_x", "positive_x", "negative_y", "positive_y", "deadzone"), &Input::get_vector, DEFVAL(-1.0f)); ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false)); ClassDB::bind_method(D_METHOD("remove_joy_mapping", "guid"), &Input::remove_joy_mapping); ClassDB::bind_method(D_METHOD("joy_connection_changed", "device", "connected", "name", "guid"), &Input::joy_connection_changed); @@ -159,10 +108,6 @@ void Input::_bind_methods() { ClassDB::bind_method(D_METHOD("get_connected_joypads"), &Input::get_connected_joypads); ClassDB::bind_method(D_METHOD("get_joy_vibration_strength", "device"), &Input::get_joy_vibration_strength); ClassDB::bind_method(D_METHOD("get_joy_vibration_duration", "device"), &Input::get_joy_vibration_duration); - ClassDB::bind_method(D_METHOD("get_joy_button_string", "button_index"), &Input::get_joy_button_string); - ClassDB::bind_method(D_METHOD("get_joy_button_index_from_string", "button"), &Input::get_joy_button_index_from_string); - ClassDB::bind_method(D_METHOD("get_joy_axis_string", "axis_index"), &Input::get_joy_axis_string); - ClassDB::bind_method(D_METHOD("get_joy_axis_index_from_string", "axis"), &Input::get_joy_axis_index_from_string); ClassDB::bind_method(D_METHOD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &Input::start_joy_vibration, DEFVAL(0)); ClassDB::bind_method(D_METHOD("stop_joy_vibration", "device"), &Input::stop_joy_vibration); ClassDB::bind_method(D_METHOD("vibrate_handheld", "duration_ms"), &Input::vibrate_handheld, DEFVAL(500)); @@ -215,7 +160,9 @@ void Input::get_argument_options(const StringName &p_function, int p_idx, List<S const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", 0) ? "'" : "\""; String pf = p_function; - if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" || pf == "is_action_just_pressed" || pf == "is_action_just_released" || pf == "get_action_strength")) { + if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" || + pf == "is_action_just_pressed" || pf == "is_action_just_released" || + pf == "get_action_strength" || pf == "get_axis" || pf == "get_vector")) { List<PropertyInfo> pinfo; ProjectSettings::get_singleton()->get_property_list(&pinfo); @@ -300,7 +247,7 @@ bool Input::is_action_just_pressed(const StringName &p_action) const { if (Engine::get_singleton()->is_in_physics_frame()) { return E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames(); } else { - return E->get().pressed && E->get().idle_frame == Engine::get_singleton()->get_idle_frames(); + return E->get().pressed && E->get().process_frame == Engine::get_singleton()->get_process_frames(); } } @@ -313,7 +260,7 @@ bool Input::is_action_just_released(const StringName &p_action) const { if (Engine::get_singleton()->is_in_physics_frame()) { return !E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames(); } else { - return !E->get().pressed && E->get().idle_frame == Engine::get_singleton()->get_idle_frames(); + return !E->get().pressed && E->get().process_frame == Engine::get_singleton()->get_process_frames(); } } @@ -326,6 +273,46 @@ float Input::get_action_strength(const StringName &p_action) const { return E->get().strength; } +float Input::get_action_raw_strength(const StringName &p_action) const { + const Map<StringName, Action>::Element *E = action_state.find(p_action); + if (!E) { + return 0.0f; + } + + return E->get().raw_strength; +} + +float Input::get_axis(const StringName &p_negative_action, const StringName &p_positive_action) const { + return get_action_strength(p_positive_action) - get_action_strength(p_negative_action); +} + +Vector2 Input::get_vector(const StringName &p_negative_x, const StringName &p_positive_x, const StringName &p_negative_y, const StringName &p_positive_y, float p_deadzone) const { + Vector2 vector = Vector2( + get_action_raw_strength(p_positive_x) - get_action_raw_strength(p_negative_x), + get_action_raw_strength(p_positive_y) - get_action_raw_strength(p_negative_y)); + + if (p_deadzone < 0.0f) { + // If the deadzone isn't specified, get it from the average of the actions. + p_deadzone = (InputMap::get_singleton()->action_get_deadzone(p_positive_x) + + InputMap::get_singleton()->action_get_deadzone(p_negative_x) + + InputMap::get_singleton()->action_get_deadzone(p_positive_y) + + InputMap::get_singleton()->action_get_deadzone(p_negative_y)) / + 4; + } + + // Circular length limiting and deadzone. + float length = vector.length(); + if (length <= p_deadzone) { + return Vector2(); + } else if (length > 1.0f) { + return vector / length; + } else { + // Inverse lerp length to map (p_deadzone, 1) to (0, 1). + return vector * (Math::inverse_lerp(p_deadzone, 1.0f, length) / length); + } + return vector; +} + float Input::get_joy_axis(int p_device, int p_axis) const { _THREAD_SAFE_METHOD_ int c = _combine_device(p_axis, p_device); @@ -601,12 +588,14 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em if (!p_event->is_echo() && is_action_pressed(E->key()) != p_event->is_action_pressed(E->key())) { Action action; action.physics_frame = Engine::get_singleton()->get_physics_frames(); - action.idle_frame = Engine::get_singleton()->get_idle_frames(); + action.process_frame = Engine::get_singleton()->get_process_frames(); action.pressed = p_event->is_action_pressed(E->key()); - action.strength = 0.f; + action.strength = 0.0f; + action.raw_strength = 0.0f; action_state[E->key()] = action; } action_state[E->key()].strength = p_event->get_action_strength(E->key()); + action_state[E->key()].raw_strength = p_event->get_action_raw_strength(E->key()); } } @@ -725,7 +714,7 @@ void Input::action_press(const StringName &p_action, float p_strength) { Action action; action.physics_frame = Engine::get_singleton()->get_physics_frames(); - action.idle_frame = Engine::get_singleton()->get_idle_frames(); + action.process_frame = Engine::get_singleton()->get_process_frames(); action.pressed = true; action.strength = p_strength; @@ -736,7 +725,7 @@ void Input::action_release(const StringName &p_action) { Action action; action.physics_frame = Engine::get_singleton()->get_physics_frames(); - action.idle_frame = Engine::get_singleton()->get_idle_frames(); + action.process_frame = Engine::get_singleton()->get_process_frames(); action.pressed = false; action.strength = 0.f; @@ -817,7 +806,7 @@ void Input::accumulate_input_event(const Ref<InputEvent> &p_event) { parse_input_event(p_event); return; } - if (!accumulated_events.empty() && accumulated_events.back()->get()->accumulate(p_event)) { + if (!accumulated_events.is_empty() && accumulated_events.back()->get()->accumulate(p_event)) { return; //event was accumulated, exit } @@ -874,7 +863,7 @@ void Input::joy_button(int p_device, int p_button, bool p_pressed) { } if (map.type == TYPE_AXIS) { - _axis_event(p_device, map.index, p_pressed ? 1.0 : 0.0); + _axis_event(p_device, map.index, p_pressed ? map.value : 0.0); } // no event? } @@ -890,14 +879,6 @@ void Input::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) { return; } - if (p_value.value > joy.last_axis[p_axis]) { - if (p_value.value < joy.last_axis[p_axis] + joy.filter) { - return; - } - } else if (p_value.value > joy.last_axis[p_axis] - joy.filter) { - return; - } - //when changing direction quickly, insert fake event to release pending inputmap actions float last = joy.last_axis[p_axis]; if (p_value.min == 0 && (last < 0.25 || last > 0.75) && (last - 0.5) * (p_value.value - 0.5) < 0) { @@ -920,55 +901,42 @@ void Input::joy_axis(int p_device, int p_axis, const JoyAxis &p_value) { return; } - JoyEvent map = _get_mapped_axis_event(map_db[joy.mapping], p_axis, p_value); + JoyEvent map = _get_mapped_axis_event(map_db[joy.mapping], p_axis, val); if (map.type == TYPE_BUTTON) { - if (map.index == JOY_BUTTON_DPAD_UP || map.index == JOY_BUTTON_DPAD_DOWN) { - bool pressed = p_value.value != 0.0f; - int button = p_value.value < 0 ? JOY_BUTTON_DPAD_UP : JOY_BUTTON_DPAD_DOWN; + bool pressed = map.value > 0.5; + if (pressed == joy_buttons_pressed.has(_combine_device(map.index, p_device))) { + // Button already pressed or released; so ignore. + return; + } + _button_event(p_device, map.index, pressed); - if (!pressed) { - if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_UP, p_device))) { - _button_event(p_device, JOY_BUTTON_DPAD_UP, false); - } + // Ensure opposite D-Pad button is also released. + switch (map.index) { + case JOY_BUTTON_DPAD_UP: if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_DOWN, p_device))) { _button_event(p_device, JOY_BUTTON_DPAD_DOWN, false); } - } - if (pressed == joy_buttons_pressed.has(_combine_device(button, p_device))) { - return; - } - _button_event(p_device, button, true); - return; - } - - if (map.index == JOY_BUTTON_DPAD_LEFT || map.index == JOY_BUTTON_DPAD_RIGHT) { - bool pressed = p_value.value != 0.0f; - int button = p_value.value < 0 ? JOY_BUTTON_DPAD_LEFT : JOY_BUTTON_DPAD_RIGHT; - - if (!pressed) { - if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_LEFT, p_device))) { - _button_event(p_device, JOY_BUTTON_DPAD_LEFT, false); + break; + case JOY_BUTTON_DPAD_DOWN: + if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_UP, p_device))) { + _button_event(p_device, JOY_BUTTON_DPAD_UP, false); } + break; + case JOY_BUTTON_DPAD_LEFT: if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_RIGHT, p_device))) { _button_event(p_device, JOY_BUTTON_DPAD_RIGHT, false); } - } - if (pressed == joy_buttons_pressed.has(_combine_device(button, p_device))) { - return; - } - _button_event(p_device, button, true); - return; - } - - float deadzone = p_value.min == 0 ? 0.5f : 0.0f; - bool pressed = p_value.value > deadzone; - if (pressed == joy_buttons_pressed.has(_combine_device(map.index, p_device))) { - // button already pressed or released, this is an axis bounce value - return; + break; + case JOY_BUTTON_DPAD_RIGHT: + if (joy_buttons_pressed.has(_combine_device(JOY_BUTTON_DPAD_LEFT, p_device))) { + _button_event(p_device, JOY_BUTTON_DPAD_LEFT, false); + } + break; + default: + // Nothing to do. + break; } - - _button_event(p_device, map.index, pressed); return; } @@ -1007,18 +975,15 @@ void Input::joy_hat(int p_device, int p_val) { int cur_val = joy_names[p_device].hat_current; - if ((p_val & HAT_MASK_UP) != (cur_val & HAT_MASK_UP)) { - _button_event(p_device, map[HAT_UP].index, p_val & HAT_MASK_UP); - } - - if ((p_val & HAT_MASK_RIGHT) != (cur_val & HAT_MASK_RIGHT)) { - _button_event(p_device, map[HAT_RIGHT].index, p_val & HAT_MASK_RIGHT); - } - if ((p_val & HAT_MASK_DOWN) != (cur_val & HAT_MASK_DOWN)) { - _button_event(p_device, map[HAT_DOWN].index, p_val & HAT_MASK_DOWN); - } - if ((p_val & HAT_MASK_LEFT) != (cur_val & HAT_MASK_LEFT)) { - _button_event(p_device, map[HAT_LEFT].index, p_val & HAT_MASK_LEFT); + for (int hat_direction = 0, hat_mask = 1; hat_direction < HAT_MAX; hat_direction++, hat_mask <<= 1) { + if ((p_val & hat_mask) != (cur_val & hat_mask)) { + if (map[hat_direction].type == TYPE_BUTTON) { + _button_event(p_device, map[hat_direction].index, p_val & hat_mask); + } + if (map[hat_direction].type == TYPE_AXIS) { + _axis_event(p_device, map[hat_direction].index, (p_val & hat_mask) ? map[hat_direction].value : 0.0); + } + } } joy_names[p_device].hat_current = p_val; @@ -1058,6 +1023,19 @@ Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, return event; case TYPE_AXIS: event.index = binding.output.axis.axis; + switch (binding.output.axis.range) { + case POSITIVE_HALF_AXIS: + event.value = 1; + break; + case NEGATIVE_HALF_AXIS: + event.value = -1; + break; + case FULL_AXIS: + // It doesn't make sense for a button to map to a full axis, + // but keeping as a default for a trigger with a positive half-axis. + event.value = 1; + break; + } return event; default: ERR_PRINT_ONCE("Joypad button mapping error."); @@ -1067,14 +1045,14 @@ Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, return event; } -Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, const JoyAxis &p_value) { +Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, float p_value) { JoyEvent event; event.type = TYPE_MAX; for (int i = 0; i < mapping.bindings.size(); i++) { const JoyBinding binding = mapping.bindings[i]; if (binding.inputType == TYPE_AXIS && binding.input.axis.axis == p_axis) { - float value = p_value.value; + float value = p_value; if (binding.input.axis.invert) { value = -value; } @@ -1082,26 +1060,40 @@ Input::JoyEvent Input::_get_mapped_axis_event(const JoyDeviceMapping &mapping, i (binding.input.axis.range == POSITIVE_HALF_AXIS && value > 0) || (binding.input.axis.range == NEGATIVE_HALF_AXIS && value < 0)) { event.type = binding.outputType; + float shifted_positive_value = 0; + switch (binding.input.axis.range) { + case POSITIVE_HALF_AXIS: + shifted_positive_value = value; + break; + case NEGATIVE_HALF_AXIS: + shifted_positive_value = value + 1; + break; + case FULL_AXIS: + shifted_positive_value = (value + 1) / 2; + break; + } switch (binding.outputType) { case TYPE_BUTTON: event.index = binding.output.button; + switch (binding.input.axis.range) { + case POSITIVE_HALF_AXIS: + event.value = shifted_positive_value; + break; + case NEGATIVE_HALF_AXIS: + event.value = 1 - shifted_positive_value; + break; + case FULL_AXIS: + // It doesn't make sense for a full axis to map to a button, + // but keeping as a default for a trigger with a positive half-axis. + event.value = (shifted_positive_value * 2) - 1; + ; + break; + } return event; case TYPE_AXIS: event.index = binding.output.axis.axis; event.value = value; if (binding.output.axis.range != binding.input.axis.range) { - float shifted_positive_value = 0; - switch (binding.input.axis.range) { - case POSITIVE_HALF_AXIS: - shifted_positive_value = value; - break; - case NEGATIVE_HALF_AXIS: - shifted_positive_value = value + 1; - break; - case FULL_AXIS: - shifted_positive_value = (value + 1) / 2; - break; - } switch (binding.output.axis.range) { case POSITIVE_HALF_AXIS: event.value = shifted_positive_value; @@ -1128,32 +1120,45 @@ void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, J for (int i = 0; i < mapping.bindings.size(); i++) { const JoyBinding binding = mapping.bindings[i]; if (binding.inputType == TYPE_HAT && binding.input.hat.hat == p_hat) { - int index; + int hat_direction; switch (binding.input.hat.hat_mask) { case HAT_MASK_UP: - index = 0; + hat_direction = HAT_UP; break; case HAT_MASK_RIGHT: - index = 1; + hat_direction = HAT_RIGHT; break; case HAT_MASK_DOWN: - index = 2; + hat_direction = HAT_DOWN; break; case HAT_MASK_LEFT: - index = 3; + hat_direction = HAT_LEFT; break; default: ERR_PRINT_ONCE("Joypad button mapping error."); continue; } - r_events[index].type = binding.outputType; + r_events[hat_direction].type = binding.outputType; switch (binding.outputType) { case TYPE_BUTTON: - r_events[index].index = binding.output.button; + r_events[hat_direction].index = binding.output.button; break; case TYPE_AXIS: - r_events[index].index = binding.output.axis.axis; + r_events[hat_direction].index = binding.output.axis.axis; + switch (binding.output.axis.range) { + case POSITIVE_HALF_AXIS: + r_events[hat_direction].value = 1; + break; + case NEGATIVE_HALF_AXIS: + r_events[hat_direction].value = -1; + break; + case FULL_AXIS: + // It doesn't make sense for a hat direction to map to a full axis, + // but keeping as a default for a trigger with a positive half-axis. + r_events[hat_direction].value = 1; + break; + } break; default: ERR_PRINT_ONCE("Joypad button mapping error."); @@ -1163,21 +1168,21 @@ void Input::_get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, J } JoyButtonList Input::_get_output_button(String output) { - for (int i = 0; _joy_buttons[i]; i++) { + for (int i = 0; i < JOY_BUTTON_SDL_MAX; i++) { if (output == _joy_buttons[i]) { return JoyButtonList(i); } } - return JoyButtonList::JOY_INVALID_BUTTON; + return JoyButtonList::JOY_BUTTON_INVALID; } JoyAxisList Input::_get_output_axis(String output) { - for (int i = 0; _joy_axes[i]; i++) { + for (int i = 0; i < JOY_AXIS_SDL_MAX; i++) { if (output == _joy_axes[i]) { return JoyAxisList(i); } } - return JoyAxisList::JOY_INVALID_AXIS; + return JoyAxisList::JOY_AXIS_INVALID; } void Input::parse_mapping(String p_mapping) { @@ -1206,19 +1211,19 @@ void Input::parse_mapping(String p_mapping) { ERR_CONTINUE_MSG(output.length() < 1 || input.length() < 2, String(entry[idx] + "\nInvalid device mapping entry: " + entry[idx])); - if (output == "platform") { + if (output == "platform" || output == "hint") { continue; } JoyAxisRange output_range = FULL_AXIS; if (output[0] == '+' || output[0] == '-') { ERR_CONTINUE_MSG(output.length() < 2, String(entry[idx] + "\nInvalid output: " + entry[idx])); - output = output.right(1); if (output[0] == '+') { output_range = POSITIVE_HALF_AXIS; } else if (output[0] == '-') { output_range = NEGATIVE_HALF_AXIS; } + output = output.right(1); } JoyAxisRange input_range = FULL_AXIS; @@ -1232,20 +1237,21 @@ void Input::parse_mapping(String p_mapping) { bool invert_axis = false; if (input[input.length() - 1] == '~') { invert_axis = true; + input = input.left(input.length() - 1); } JoyButtonList output_button = _get_output_button(output); JoyAxisList output_axis = _get_output_axis(output); - ERR_CONTINUE_MSG(output_button == JOY_INVALID_BUTTON && output_axis == JOY_INVALID_AXIS, + ERR_CONTINUE_MSG(output_button == JOY_BUTTON_INVALID && output_axis == JOY_AXIS_INVALID, String(entry[idx] + "\nUnrecognised output string: " + output)); - ERR_CONTINUE_MSG(output_button != JOY_INVALID_BUTTON && output_axis != JOY_INVALID_AXIS, + ERR_CONTINUE_MSG(output_button != JOY_BUTTON_INVALID && output_axis != JOY_AXIS_INVALID, String("BUG: Output string matched both button and axis: " + output)); JoyBinding binding; - if (output_button != JOY_INVALID_BUTTON) { + if (output_button != JOY_BUTTON_INVALID) { binding.outputType = TYPE_BUTTON; binding.output.button = output_button; - } else if (output_axis != JOY_INVALID_AXIS) { + } else if (output_axis != JOY_AXIS_INVALID) { binding.outputType = TYPE_AXIS; binding.output.axis.axis = output_axis; binding.output.axis.range = output_range; @@ -1337,20 +1343,6 @@ Array Input::get_connected_joypads() { return ret; } -String Input::get_joy_button_string(int p_button) { - ERR_FAIL_INDEX_V(p_button, JOY_BUTTON_MAX, "Invalid button"); - return _joy_button_names[p_button]; -} - -int Input::get_joy_button_index_from_string(String p_button) { - for (int i = 0; i < JOY_BUTTON_MAX; i++) { - if (p_button == _joy_button_names[i]) { - return i; - } - } - ERR_FAIL_V(JOY_INVALID_BUTTON); -} - int Input::get_unused_joy_id() { for (int i = 0; i < JOYPADS_MAX; i++) { if (!joy_names.has(i) || !joy_names[i].connected) { @@ -1360,20 +1352,6 @@ int Input::get_unused_joy_id() { return -1; } -String Input::get_joy_axis_string(int p_axis) { - ERR_FAIL_INDEX_V(p_axis, JOY_AXIS_MAX, "Invalid axis"); - return _joy_axis_names[p_axis]; -} - -int Input::get_joy_axis_index_from_string(String p_axis) { - for (int i = 0; i < JOY_AXIS_MAX; i++) { - if (p_axis == _joy_axis_names[i]) { - return i; - } - } - ERR_FAIL_V(JOY_INVALID_AXIS); -} - Input::Input() { singleton = this; diff --git a/core/input/input.h b/core/input/input.h index 775663503b..445b7ff0cf 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,7 @@ #define INPUT_H #include "core/input/input_event.h" -#include "core/object.h" +#include "core/object/object.h" #include "core/os/thread_safe.h" class Input : public Object { @@ -114,9 +114,10 @@ private: struct Action { uint64_t physics_frame; - uint64_t idle_frame; + uint64_t process_frame; bool pressed; float strength; + float raw_strength; }; Map<StringName, Action> action_state; @@ -146,7 +147,6 @@ private: bool connected = false; bool last_buttons[JOY_BUTTON_MAX] = { false }; float last_axis[JOY_AXIS_MAX] = { 0.0f }; - float filter = 0.01f; int last_hat = HAT_MASK_CENTER; int mapping = -1; int hat_current = 0; @@ -217,13 +217,12 @@ private: Vector<JoyDeviceMapping> map_db; JoyEvent _get_mapped_button_event(const JoyDeviceMapping &mapping, int p_button); - JoyEvent _get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, const JoyAxis &p_value); + JoyEvent _get_mapped_axis_event(const JoyDeviceMapping &mapping, int p_axis, float p_value); void _get_mapped_hat_events(const JoyDeviceMapping &mapping, int p_hat, JoyEvent r_events[HAT_MAX]); JoyButtonList _get_output_button(String output); JoyAxisList _get_output_axis(String output); void _button_event(int p_device, int p_index, bool p_pressed); void _axis_event(int p_device, int p_axis, float p_value); - float _handle_deadzone(int p_device, int p_axis, float p_value); void _parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated); @@ -266,6 +265,10 @@ public: bool is_action_just_pressed(const StringName &p_action) const; bool is_action_just_released(const StringName &p_action) const; float get_action_strength(const StringName &p_action) const; + float get_action_raw_strength(const StringName &p_action) const; + + float get_axis(const StringName &p_negative_action, const StringName &p_positive_action) const; + Vector2 get_vector(const StringName &p_negative_x, const StringName &p_positive_x, const StringName &p_negative_y, const StringName &p_positive_y, float p_deadzone = -1.0f) const; float get_joy_axis(int p_device, int p_axis) const; String get_joy_name(int p_idx); @@ -327,11 +330,6 @@ public: void add_joy_mapping(String p_mapping, bool p_update_existing = false); void remove_joy_mapping(String p_guid); - String get_joy_button_string(int p_button); - String get_joy_axis_string(int p_axis); - int get_joy_axis_index_from_string(String p_axis); - int get_joy_button_index_from_string(String p_button); - int get_unused_joy_id(); bool is_joy_known(int p_device); diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 6ba082f86f..2771a15b80 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -61,12 +61,17 @@ bool InputEvent::is_action_released(const StringName &p_action) const { } float InputEvent::get_action_strength(const StringName &p_action) const { - bool pressed; float strength; - bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, &pressed, &strength); + bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, nullptr, &strength); return valid ? strength : 0.0f; } +float InputEvent::get_action_raw_strength(const StringName &p_action) const { + float raw_strength; + bool valid = InputMap::get_singleton()->event_get_action_status(Ref<InputEvent>((InputEvent *)this), p_action, nullptr, nullptr, &raw_strength); + return valid ? raw_strength : 0.0f; +} + bool InputEvent::is_pressed() const { return false; } @@ -79,11 +84,7 @@ Ref<InputEvent> InputEvent::xformed_by(const Transform2D &p_xform, const Vector2 return Ref<InputEvent>((InputEvent *)this); } -String InputEvent::as_text() const { - return String(); -} - -bool InputEvent::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { +bool InputEvent::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const { return false; } @@ -138,6 +139,14 @@ int64_t InputEventFromWindow::get_window_id() const { /////////////////////////////////// +void InputEventWithModifiers::set_store_command(bool p_enabled) { + store_command = p_enabled; +} + +bool InputEventWithModifiers::is_storing_command() const { + return store_command; +} + void InputEventWithModifiers::set_shift(bool p_enabled) { shift = p_enabled; } @@ -185,7 +194,37 @@ void InputEventWithModifiers::set_modifiers_from_event(const InputEventWithModif set_metakey(event->get_metakey()); } +String InputEventWithModifiers::as_text() const { + Vector<String> mod_names; + + if (get_control()) { + mod_names.push_back(find_keycode_name(KEY_CONTROL)); + } + if (get_shift()) { + mod_names.push_back(find_keycode_name(KEY_SHIFT)); + } + if (get_alt()) { + mod_names.push_back(find_keycode_name(KEY_ALT)); + } + if (get_metakey()) { + mod_names.push_back(find_keycode_name(KEY_META)); + } + + if (!mod_names.is_empty()) { + return String("+").join(mod_names); + } else { + return ""; + } +} + +String InputEventWithModifiers::to_string() { + return as_text(); +} + void InputEventWithModifiers::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_store_command", "enable"), &InputEventWithModifiers::set_store_command); + ClassDB::bind_method(D_METHOD("is_storing_command"), &InputEventWithModifiers::is_storing_command); + ClassDB::bind_method(D_METHOD("set_alt", "enable"), &InputEventWithModifiers::set_alt); ClassDB::bind_method(D_METHOD("get_alt"), &InputEventWithModifiers::get_alt); @@ -201,6 +240,7 @@ void InputEventWithModifiers::_bind_methods() { ClassDB::bind_method(D_METHOD("set_command", "enable"), &InputEventWithModifiers::set_command); ClassDB::bind_method(D_METHOD("get_command"), &InputEventWithModifiers::get_command); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "store_command"), "set_store_command", "is_storing_command"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "alt"), "set_alt", "get_alt"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shift"), "set_shift", "get_shift"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "control"), "set_control", "get_control"); @@ -208,6 +248,28 @@ void InputEventWithModifiers::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "command"), "set_command", "get_command"); } +void InputEventWithModifiers::_validate_property(PropertyInfo &property) const { + if (store_command) { + // If we only want to Store "Command". +#ifdef APPLE_STYLE_KEYS + // Don't store "Meta" on Mac. + if (property.name == "meta") { + property.usage ^= PROPERTY_USAGE_STORAGE; + } +#else + // Don't store "Control". + if (property.name == "control") { + property.usage ^= PROPERTY_USAGE_STORAGE; + } +#endif + } else { + // We don't want to store command, only control or meta (on mac). + if (property.name == "command") { + property.usage ^= PROPERTY_USAGE_STORAGE; + } + } +} + /////////////////////////////////// void InputEventKey::set_pressed(bool p_pressed) { @@ -287,27 +349,42 @@ uint32_t InputEventKey::get_physical_keycode_with_modifiers() const { } String InputEventKey::as_text() const { - String kc = keycode_get_string(keycode); + String kc; + + if (keycode == 0) { + kc = keycode_get_string(physical_keycode) + " (" + RTR("Physical") + ")"; + } else { + kc = keycode_get_string(keycode); + } + if (kc == String()) { return kc; } - if (get_metakey()) { - kc = find_keycode_name(KEY_META) + ("+" + kc); - } - if (get_alt()) { - kc = find_keycode_name(KEY_ALT) + ("+" + kc); - } - if (get_shift()) { - kc = find_keycode_name(KEY_SHIFT) + ("+" + kc); - } - if (get_control()) { - kc = find_keycode_name(KEY_CONTROL) + ("+" + kc); + String mods_text = InputEventWithModifiers::as_text(); + return mods_text == "" ? kc : mods_text + "+" + kc; +} + +String InputEventKey::to_string() { + String p = is_pressed() ? "true" : "false"; + String e = is_echo() ? "true" : "false"; + + String kc = ""; + String physical = "false"; + if (keycode == 0) { + kc = itos(physical_keycode) + " " + keycode_get_string(physical_keycode); + physical = "true"; + } else { + kc = itos(keycode) + " " + keycode_get_string(keycode); } - return kc; + + String mods = InputEventWithModifiers::as_text(); + mods = mods == "" ? TTR("None") : mods; + + return vformat("InputEventKey: keycode=%s mods=%s physical=%s pressed=%s echo=%s", kc, mods, physical, p, e); } -bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { +bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const { Ref<InputEventKey> key = p_event; if (key.is_null()) { return false; @@ -329,8 +406,12 @@ bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool *p_pressed if (p_pressed != nullptr) { *p_pressed = key->is_pressed(); } + float strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f; if (p_strength != nullptr) { - *p_strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f; + *p_strength = strength; + } + if (p_raw_strength != nullptr) { + *p_raw_strength = strength; } } return match; @@ -470,7 +551,7 @@ Ref<InputEvent> InputEventMouseButton::xformed_by(const Transform2D &p_xform, co return mb; } -bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { +bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const { Ref<InputEventMouseButton> mb = p_event; if (mb.is_null()) { return false; @@ -481,49 +562,91 @@ bool InputEventMouseButton::action_match(const Ref<InputEvent> &p_event, bool *p if (p_pressed != nullptr) { *p_pressed = mb->is_pressed(); } + float strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f; if (p_strength != nullptr) { - *p_strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f; + *p_strength = strength; + } + if (p_raw_strength != nullptr) { + *p_raw_strength = strength; } } return match; } +static const char *_mouse_button_descriptions[9] = { + TTRC("Left Mouse Button"), + TTRC("Right Mouse Button"), + TTRC("Middle Mouse Button"), + TTRC("Mouse Wheel Up"), + TTRC("Mouse Wheel Down"), + TTRC("Mouse Wheel Left"), + TTRC("Mouse Wheel Right"), + TTRC("Mouse Thumb Button 1"), + TTRC("Mouse Thumb Button 2") +}; + String InputEventMouseButton::as_text() const { - String button_index_string = ""; - switch (get_button_index()) { + // Modifiers + String mods_text = InputEventWithModifiers::as_text(); + String full_string = mods_text == "" ? "" : mods_text + "+"; + + // Button + int idx = get_button_index(); + switch (idx) { case BUTTON_LEFT: - button_index_string = "BUTTON_LEFT"; - break; case BUTTON_RIGHT: - button_index_string = "BUTTON_RIGHT"; - break; case BUTTON_MIDDLE: - button_index_string = "BUTTON_MIDDLE"; - break; case BUTTON_WHEEL_UP: - button_index_string = "BUTTON_WHEEL_UP"; - break; case BUTTON_WHEEL_DOWN: - button_index_string = "BUTTON_WHEEL_DOWN"; - break; case BUTTON_WHEEL_LEFT: - button_index_string = "BUTTON_WHEEL_LEFT"; - break; case BUTTON_WHEEL_RIGHT: - button_index_string = "BUTTON_WHEEL_RIGHT"; - break; case BUTTON_XBUTTON1: - button_index_string = "BUTTON_XBUTTON1"; + case BUTTON_XBUTTON2: + full_string += RTR(_mouse_button_descriptions[idx - 1]); // button index starts from 1, array index starts from 0, so subtract 1 break; + default: + full_string += RTR("Button") + " #" + itos(idx); + break; + } + + // Double Click + if (doubleclick) { + full_string += " (" + RTR("Double Click") + ")"; + } + + return full_string; +} + +String InputEventMouseButton::to_string() { + String p = is_pressed() ? "true" : "false"; + String d = doubleclick ? "true" : "false"; + + int idx = get_button_index(); + String button_string = itos(idx); + + switch (idx) { + case BUTTON_LEFT: + case BUTTON_RIGHT: + case BUTTON_MIDDLE: + case BUTTON_WHEEL_UP: + case BUTTON_WHEEL_DOWN: + case BUTTON_WHEEL_LEFT: + case BUTTON_WHEEL_RIGHT: + case BUTTON_XBUTTON1: case BUTTON_XBUTTON2: - button_index_string = "BUTTON_XBUTTON2"; + button_string += " (" + RTR(_mouse_button_descriptions[idx - 1]) + ")"; // button index starts from 1, array index starts from 0, so subtract 1 break; default: - button_index_string = itos(get_button_index()); break; } - return "InputEventMouseButton : button_index=" + button_index_string + ", pressed=" + (pressed ? "true" : "false") + ", position=(" + String(get_position()) + "), button_mask=" + itos(get_button_mask()) + ", doubleclick=" + (doubleclick ? "true" : "false"); + + String mods = InputEventWithModifiers::as_text(); + mods = mods == "" ? TTR("None") : mods; + + // Work around the fact vformat can only take 5 substitutions but 6 need to be passed. + String index_and_mods = vformat("button_index=%s mods=%s", button_index, mods); + return vformat("InputEventMouseButton: %s pressed=%s position=(%s) button_mask=%s doubleclick=%s", index_and_mods, p, String(get_position()), itos(get_button_mask()), d); } void InputEventMouseButton::_bind_methods() { @@ -606,27 +729,32 @@ Ref<InputEvent> InputEventMouseMotion::xformed_by(const Transform2D &p_xform, co } String InputEventMouseMotion::as_text() const { - String button_mask_string = ""; + return vformat(RTR("Mouse motion at position (%s) with speed (%s)"), String(get_position()), String(get_speed())); +} + +String InputEventMouseMotion::to_string() { + int button_mask = get_button_mask(); + String button_mask_string = itos(button_mask); switch (get_button_mask()) { case BUTTON_MASK_LEFT: - button_mask_string = "BUTTON_MASK_LEFT"; + button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_LEFT - 1]) + ")"; break; case BUTTON_MASK_MIDDLE: - button_mask_string = "BUTTON_MASK_MIDDLE"; + button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_MIDDLE - 1]) + ")"; break; case BUTTON_MASK_RIGHT: - button_mask_string = "BUTTON_MASK_RIGHT"; + button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_RIGHT - 1]) + ")"; break; case BUTTON_MASK_XBUTTON1: - button_mask_string = "BUTTON_MASK_XBUTTON1"; + button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_XBUTTON1 - 1]) + ")"; break; case BUTTON_MASK_XBUTTON2: - button_mask_string = "BUTTON_MASK_XBUTTON2"; + button_mask_string += " (" + RTR(_mouse_button_descriptions[BUTTON_XBUTTON2 - 1]) + ")"; break; default: - button_mask_string = itos(get_button_mask()); break; } + return "InputEventMouseMotion : button_mask=" + button_mask_string + ", position=(" + String(get_position()) + "), relative=(" + String(get_relative()) + "), speed=(" + String(get_speed()) + "), pressure=(" + rtos(get_pressure()) + "), tilt=(" + String(get_tilt()) + ")"; } @@ -713,7 +841,7 @@ bool InputEventJoypadMotion::is_pressed() const { return Math::abs(axis_value) >= 0.5f; } -bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { +bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const { Ref<InputEventJoypadMotion> jm = p_event; if (jm.is_null()) { return false; @@ -721,8 +849,9 @@ bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool * bool match = (axis == jm->axis); // Matches even if not in the same direction, but returns a "not pressed" event. if (match) { + float jm_abs_axis_value = Math::abs(jm->get_axis_value()); bool same_direction = (((axis_value < 0) == (jm->axis_value < 0)) || jm->axis_value == 0); - bool pressed = same_direction ? Math::abs(jm->get_axis_value()) >= p_deadzone : false; + bool pressed = same_direction && jm_abs_axis_value >= p_deadzone; if (p_pressed != nullptr) { *p_pressed = pressed; } @@ -731,17 +860,43 @@ bool InputEventJoypadMotion::action_match(const Ref<InputEvent> &p_event, bool * if (p_deadzone == 1.0f) { *p_strength = 1.0f; } else { - *p_strength = CLAMP(Math::inverse_lerp(p_deadzone, 1.0f, Math::abs(jm->get_axis_value())), 0.0f, 1.0f); + *p_strength = CLAMP(Math::inverse_lerp(p_deadzone, 1.0f, jm_abs_axis_value), 0.0f, 1.0f); } } else { *p_strength = 0.0f; } } + if (p_raw_strength != nullptr) { + if (same_direction) { // NOT pressed, because we want to ignore the deadzone. + *p_raw_strength = jm_abs_axis_value; + } else { + *p_raw_strength = 0.0f; + } + } } return match; } +static const char *_joy_axis_descriptions[JOY_AXIS_MAX] = { + TTRC("Left Stick X-Axis, Joystick 0 X-Axis"), + TTRC("Left Stick Y-Axis, Joystick 0 Y-Axis"), + TTRC("Right Stick X-Axis, Joystick 1 X-Axis"), + TTRC("Right Stick Y-Axis, Joystick 1 Y-Axis"), + TTRC("Joystick 2 X-Axis, Left Trigger, Sony L2, Xbox LT"), + TTRC("Joystick 2 Y-Axis, Right Trigger, Sony R2, Xbox RT"), + TTRC("Joystick 3 X-Axis"), + TTRC("Joystick 3 Y-Axis"), + TTRC("Joystick 4 X-Axis"), + TTRC("Joystick 4 Y-Axis"), +}; + String InputEventJoypadMotion::as_text() const { + String desc = axis < JOY_AXIS_MAX ? RTR(_joy_axis_descriptions[axis]) : TTR("Unknown Joypad Axis"); + + return vformat(TTR("Joypad Motion on Axis %s (%s) with Value %s"), itos(axis), desc, String(Variant(axis_value))); +} + +String InputEventJoypadMotion::to_string() { return "InputEventJoypadMotion : axis=" + itos(axis) + ", axis_value=" + String(Variant(axis_value)); } @@ -782,7 +937,7 @@ float InputEventJoypadButton::get_pressure() const { return pressure; } -bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { +bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const { Ref<InputEventJoypadButton> jb = p_event; if (jb.is_null()) { return false; @@ -793,8 +948,12 @@ bool InputEventJoypadButton::action_match(const Ref<InputEvent> &p_event, bool * if (p_pressed != nullptr) { *p_pressed = jb->is_pressed(); } + float strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f; if (p_strength != nullptr) { - *p_strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f; + *p_strength = strength; + } + if (p_raw_strength != nullptr) { + *p_raw_strength = strength; } } @@ -810,7 +969,39 @@ bool InputEventJoypadButton::shortcut_match(const Ref<InputEvent> &p_event) cons return button_index == button->button_index; } +static const char *_joy_button_descriptions[JOY_BUTTON_SDL_MAX] = { + TTRC("Bottom Action, Sony Cross, Xbox A, Nintendo B"), + TTRC("Right Action, Sony Circle, Xbox B, Nintendo A"), + TTRC("Left Action, Sony Square, Xbox X, Nintendo Y"), + TTRC("Top Action, Sony Triangle, Xbox Y, Nintendo X"), + TTRC("Back, Sony Select, Xbox Back, Nintendo -"), + TTRC("Guide, Sony PS, Xbox Home"), + TTRC("Start, Nintendo +"), + TTRC("Left Stick, Sony L3, Xbox L/LS"), + TTRC("Right Stick, Sony R3, Xbox R/RS"), + TTRC("Left Shoulder, Sony L1, Xbox LB"), + TTRC("Right Shoulder, Sony R1, Xbox RB"), + TTRC("D-pad Up"), + TTRC("D-pad Down"), + TTRC("D-pad Left"), + TTRC("D-pad Right"), +}; + String InputEventJoypadButton::as_text() const { + String text = "Joypad Button " + itos(button_index); + + if (button_index < JOY_BUTTON_SDL_MAX) { + text += vformat(" (%s)", _joy_button_descriptions[button_index]); + } + + if (pressure != 0) { + text += ", Pressure:" + String(Variant(pressure)); + } + + return text; +} + +String InputEventJoypadButton::to_string() { return "InputEventJoypadButton : button_index=" + itos(button_index) + ", pressed=" + (pressed ? "true" : "false") + ", pressure=" + String(Variant(pressure)); } @@ -868,6 +1059,12 @@ Ref<InputEvent> InputEventScreenTouch::xformed_by(const Transform2D &p_xform, co } String InputEventScreenTouch::as_text() const { + String status = pressed ? RTR("touched") : RTR("released"); + + return vformat(RTR("Screen %s at (%s) with %s touch points"), status, String(get_position()), itos(index)); +} + +String InputEventScreenTouch::to_string() { return "InputEventScreenTouch : index=" + itos(index) + ", pressed=" + (pressed ? "true" : "false") + ", position=(" + String(get_position()) + ")"; } @@ -937,6 +1134,10 @@ Ref<InputEvent> InputEventScreenDrag::xformed_by(const Transform2D &p_xform, con } String InputEventScreenDrag::as_text() const { + return vformat(RTR("Screen dragged with %s touch points at position (%s) with speed of (%s)"), itos(index), String(get_position()), String(get_speed())); +} + +String InputEventScreenDrag::to_string() { return "InputEventScreenDrag : index=" + itos(index) + ", position=(" + String(get_position()) + "), relative=(" + String(get_relative()) + "), speed=(" + String(get_speed()) + ")"; } @@ -997,7 +1198,7 @@ bool InputEventAction::is_action(const StringName &p_action) const { return action == p_action; } -bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const { +bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const { Ref<InputEventAction> act = p_event; if (act.is_null()) { return false; @@ -1008,14 +1209,22 @@ bool InputEventAction::action_match(const Ref<InputEvent> &p_event, bool *p_pres if (p_pressed != nullptr) { *p_pressed = act->pressed; } + float strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f; if (p_strength != nullptr) { - *p_strength = (p_pressed != nullptr && *p_pressed) ? 1.0f : 0.0f; + *p_strength = strength; + } + if (p_raw_strength != nullptr) { + *p_raw_strength = strength; } } return match; } String InputEventAction::as_text() const { + return vformat(RTR("Input Action %s was %s"), action, pressed ? "pressed" : "released"); +} + +String InputEventAction::to_string() { return "InputEventAction : action=" + action + ", pressed=(" + (pressed ? "true" : "false"); } @@ -1079,6 +1288,10 @@ Ref<InputEvent> InputEventMagnifyGesture::xformed_by(const Transform2D &p_xform, } String InputEventMagnifyGesture::as_text() const { + return vformat(RTR("Magnify Gesture at (%s) with factor %s"), String(get_position()), rtos(get_factor())); +} + +String InputEventMagnifyGesture::to_string() { return "InputEventMagnifyGesture : factor=" + rtos(get_factor()) + ", position=(" + String(get_position()) + ")"; } @@ -1115,6 +1328,10 @@ Ref<InputEvent> InputEventPanGesture::xformed_by(const Transform2D &p_xform, con } String InputEventPanGesture::as_text() const { + return vformat(RTR("Pan Gesture at (%s) with delta (%s)"), String(get_position()), String(get_delta())); +} + +String InputEventPanGesture::to_string() { return "InputEventPanGesture : delta=(" + String(get_delta()) + "), position=(" + String(get_position()) + ")"; } @@ -1192,7 +1409,11 @@ int InputEventMIDI::get_controller_value() const { } String InputEventMIDI::as_text() const { - return "InputEventMIDI : channel=(" + itos(get_channel()) + "), message=(" + itos(get_message()) + ")"; + return vformat(RTR("MIDI Input on Channel=%s Message=%s"), itos(channel), itos(message)); +} + +String InputEventMIDI::to_string() { + return vformat("InputEvenMIDI: channel=%s message=%s pitch=%s velocity=%s pressure=%s", itos(channel), itos(message), itos(pitch), itos(velocity), itos(pressure)); } void InputEventMIDI::_bind_methods() { diff --git a/core/input/input_event.h b/core/input/input_event.h index 815ba5ae80..1500faa24c 100644 --- a/core/input/input_event.h +++ b/core/input/input_event.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,11 +31,11 @@ #ifndef INPUT_EVENT_H #define INPUT_EVENT_H +#include "core/io/resource.h" #include "core/math/transform_2d.h" #include "core/os/copymem.h" -#include "core/resource.h" +#include "core/string/ustring.h" #include "core/typedefs.h" -#include "core/ustring.h" /** * Input Event classes. These are used in the main loop. @@ -60,10 +60,7 @@ enum ButtonList { }; enum JoyButtonList { - - JOY_INVALID_BUTTON = -1, - - // SDL Buttons + JOY_BUTTON_INVALID = -1, JOY_BUTTON_A = 0, JOY_BUTTON_B = 1, JOY_BUTTON_X = 2, @@ -79,64 +76,20 @@ enum JoyButtonList { JOY_BUTTON_DPAD_DOWN = 12, JOY_BUTTON_DPAD_LEFT = 13, JOY_BUTTON_DPAD_RIGHT = 14, - JOY_SDL_BUTTONS = 15, - - // Sony Buttons - JOY_SONY_X = JOY_BUTTON_A, - JOY_SONY_CROSS = JOY_BUTTON_A, - JOY_SONY_CIRCLE = JOY_BUTTON_B, - JOY_SONY_SQUARE = JOY_BUTTON_X, - JOY_SONY_TRIANGLE = JOY_BUTTON_Y, - JOY_SONY_SELECT = JOY_BUTTON_BACK, - JOY_SONY_START = JOY_BUTTON_START, - JOY_SONY_PS = JOY_BUTTON_GUIDE, - JOY_SONY_L1 = JOY_BUTTON_LEFT_SHOULDER, - JOY_SONY_R1 = JOY_BUTTON_RIGHT_SHOULDER, - JOY_SONY_L3 = JOY_BUTTON_LEFT_STICK, - JOY_SONY_R3 = JOY_BUTTON_RIGHT_STICK, - - // Xbox Buttons - JOY_XBOX_A = JOY_BUTTON_A, - JOY_XBOX_B = JOY_BUTTON_B, - JOY_XBOX_X = JOY_BUTTON_X, - JOY_XBOX_Y = JOY_BUTTON_Y, - JOY_XBOX_BACK = JOY_BUTTON_BACK, - JOY_XBOX_START = JOY_BUTTON_START, - JOY_XBOX_HOME = JOY_BUTTON_GUIDE, - JOY_XBOX_LS = JOY_BUTTON_LEFT_STICK, - JOY_XBOX_RS = JOY_BUTTON_RIGHT_STICK, - JOY_XBOX_LB = JOY_BUTTON_LEFT_SHOULDER, - JOY_XBOX_RB = JOY_BUTTON_RIGHT_SHOULDER, - - JOY_BUTTON_MAX = 36 // Apparently Android supports up to 36 buttons. + JOY_BUTTON_SDL_MAX = 15, + JOY_BUTTON_MAX = 36, // Android supports up to 36 buttons. }; enum JoyAxisList { - - JOY_INVALID_AXIS = -1, - - // SDL Axes + JOY_AXIS_INVALID = -1, JOY_AXIS_LEFT_X = 0, JOY_AXIS_LEFT_Y = 1, JOY_AXIS_RIGHT_X = 2, JOY_AXIS_RIGHT_Y = 3, JOY_AXIS_TRIGGER_LEFT = 4, JOY_AXIS_TRIGGER_RIGHT = 5, - JOY_SDL_AXES = 6, - - // Joystick axes. - JOY_AXIS_0_X = 0, - JOY_AXIS_0_Y = 1, - JOY_AXIS_1_X = 2, - JOY_AXIS_1_Y = 3, - JOY_AXIS_2_X = 4, - JOY_AXIS_2_Y = 5, - JOY_AXIS_3_X = 6, - JOY_AXIS_3_Y = 7, - JOY_AXIS_4_X = 8, - JOY_AXIS_4_Y = 9, - - JOY_AXIS_MAX = 10 // OpenVR supports up to 5 Joysticks making a total of 10 axes. + JOY_AXIS_SDL_MAX = 6, + JOY_AXIS_MAX = 10, // OpenVR supports up to 5 Joysticks making a total of 10 axes. }; enum MidiMessageList { @@ -173,16 +126,17 @@ public: bool is_action_pressed(const StringName &p_action, bool p_allow_echo = false) const; bool is_action_released(const StringName &p_action) const; float get_action_strength(const StringName &p_action) const; + float get_action_raw_strength(const StringName &p_action) const; // To be removed someday, since they do not make sense for all events virtual bool is_pressed() const; virtual bool is_echo() const; - virtual String as_text() const; + virtual String as_text() const = 0; virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const; - virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const; + virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const; virtual bool shortcut_match(const Ref<InputEvent> &p_event) const; virtual bool is_action_type() const; @@ -209,6 +163,8 @@ public: class InputEventWithModifiers : public InputEventFromWindow { GDCLASS(InputEventWithModifiers, InputEventFromWindow); + bool store_command = true; + bool shift = false; bool alt = false; #ifdef APPLE_STYLE_KEYS @@ -228,8 +184,12 @@ class InputEventWithModifiers : public InputEventFromWindow { protected: static void _bind_methods(); + virtual void _validate_property(PropertyInfo &property) const override; public: + void set_store_command(bool p_enabled); + bool is_storing_command() const; + void set_shift(bool p_enabled); bool get_shift() const; @@ -247,6 +207,9 @@ public: void set_modifiers_from_event(const InputEventWithModifiers *event); + virtual String as_text() const override; + virtual String to_string() override; + InputEventWithModifiers() {} }; @@ -283,12 +246,13 @@ public: uint32_t get_keycode_with_modifiers() const; uint32_t get_physical_keycode_with_modifiers() const; - virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const override; + virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override; virtual bool shortcut_match(const Ref<InputEvent> &p_event) const override; virtual bool is_action_type() const override { return true; } virtual String as_text() const override; + virtual String to_string() override; InputEventKey() {} }; @@ -342,10 +306,11 @@ public: bool is_doubleclick() const; virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override; - virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const override; + virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override; virtual bool is_action_type() const override { return true; } virtual String as_text() const override; + virtual String to_string() override; InputEventMouseButton() {} }; @@ -376,6 +341,7 @@ public: virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override; virtual String as_text() const override; + virtual String to_string() override; virtual bool accumulate(const Ref<InputEvent> &p_event) override; @@ -399,10 +365,11 @@ public: virtual bool is_pressed() const override; - virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const override; + virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override; virtual bool is_action_type() const override { return true; } virtual String as_text() const override; + virtual String to_string() override; InputEventJoypadMotion() {} }; @@ -426,11 +393,12 @@ public: void set_pressure(float p_pressure); float get_pressure() const; - virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const override; + virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override; virtual bool shortcut_match(const Ref<InputEvent> &p_event) const override; virtual bool is_action_type() const override { return true; } virtual String as_text() const override; + virtual String to_string() override; InputEventJoypadButton() {} }; @@ -456,6 +424,7 @@ public: virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override; virtual String as_text() const override; + virtual String to_string() override; InputEventScreenTouch() {} }; @@ -485,6 +454,7 @@ public: virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override; virtual String as_text() const override; + virtual String to_string() override; InputEventScreenDrag() {} }; @@ -511,11 +481,12 @@ public: virtual bool is_action(const StringName &p_action) const; - virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float p_deadzone) const override; + virtual bool action_match(const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength, float p_deadzone) const override; virtual bool shortcut_match(const Ref<InputEvent> &p_event) const override; virtual bool is_action_type() const override { return true; } virtual String as_text() const override; + virtual String to_string() override; InputEventAction() {} }; @@ -546,6 +517,7 @@ public: virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override; virtual String as_text() const override; + virtual String to_string() override; InputEventMagnifyGesture() {} }; @@ -563,6 +535,7 @@ public: virtual Ref<InputEvent> xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const override; virtual String as_text() const override; + virtual String to_string() override; InputEventPanGesture() {} }; @@ -608,6 +581,7 @@ public: int get_controller_value() const; virtual String as_text() const override; + virtual String to_string() override; InputEventMIDI() {} }; diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index 6319ffc8f1..53ed925c1f 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,8 +30,9 @@ #include "input_map.h" +#include "core/config/project_settings.h" +#include "core/input/input.h" #include "core/os/keyboard.h" -#include "core/project_settings.h" InputMap *InputMap::singleton = nullptr; @@ -50,7 +51,7 @@ void InputMap::_bind_methods() { ClassDB::bind_method(D_METHOD("action_erase_events", "action"), &InputMap::action_erase_events); ClassDB::bind_method(D_METHOD("action_get_events", "action"), &InputMap::_action_get_events); ClassDB::bind_method(D_METHOD("event_is_action", "event", "action"), &InputMap::event_is_action); - ClassDB::bind_method(D_METHOD("load_from_globals"), &InputMap::load_from_globals); + ClassDB::bind_method(D_METHOD("load_from_project_settings"), &InputMap::load_from_project_settings); } void InputMap::add_action(const StringName &p_action, float p_deadzone) { @@ -70,7 +71,7 @@ void InputMap::erase_action(const StringName &p_action) { Array InputMap::_get_actions() { Array ret; List<StringName> actions = get_actions(); - if (actions.empty()) { + if (actions.is_empty()) { return ret; } @@ -83,7 +84,7 @@ Array InputMap::_get_actions() { List<StringName> InputMap::get_actions() const { List<StringName> actions = List<StringName>(); - if (input_map.empty()) { + if (input_map.is_empty()) { return actions; } @@ -94,7 +95,7 @@ List<StringName> InputMap::get_actions() const { return actions; } -List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength) const { +List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed, float *p_strength, float *p_raw_strength) const { ERR_FAIL_COND_V(!p_event.is_valid(), nullptr); for (List<Ref<InputEvent>>::Element *E = p_action.inputs.front(); E; E = E->next()) { @@ -105,7 +106,7 @@ List<Ref<InputEvent>>::Element *InputMap::_find_event(Action &p_action, const Re int device = e->get_device(); if (device == ALL_DEVICES || device == p_event->get_device()) { - if (e->action_match(p_event, p_pressed, p_strength, p_action.deadzone)) { + if (e->action_match(p_event, p_pressed, p_strength, p_raw_strength, p_action.deadzone)) { return E; } } @@ -118,6 +119,12 @@ bool InputMap::has_action(const StringName &p_action) const { return input_map.has(p_action); } +float InputMap::action_get_deadzone(const StringName &p_action) { + ERR_FAIL_COND_V_MSG(!input_map.has(p_action), 0.0f, "Request for nonexistent InputMap action '" + String(p_action) + "'."); + + return input_map[p_action].deadzone; +} + void InputMap::action_set_deadzone(const StringName &p_action, float p_deadzone) { ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'."); @@ -145,6 +152,9 @@ void InputMap::action_erase_event(const StringName &p_action, const Ref<InputEve List<Ref<InputEvent>>::Element *E = _find_event(input_map[p_action], p_event); if (E) { input_map[p_action].inputs.erase(E); + if (Input::get_singleton()->is_action_pressed(p_action)) { + Input::get_singleton()->action_release(p_action); + } } } @@ -179,7 +189,7 @@ bool InputMap::event_is_action(const Ref<InputEvent> &p_event, const StringName return event_get_action_status(p_event, p_action); } -bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed, float *p_strength) const { +bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed, float *p_strength, float *p_raw_strength) const { Map<StringName, Action>::Element *E = input_map.find(p_action); ERR_FAIL_COND_V_MSG(!E, false, "Request for nonexistent InputMap action '" + String(p_action) + "'."); @@ -196,7 +206,8 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str bool pressed; float strength; - List<Ref<InputEvent>>::Element *event = _find_event(E->get(), p_event, &pressed, &strength); + float raw_strength; + List<Ref<InputEvent>>::Element *event = _find_event(E->get(), p_event, &pressed, &strength, &raw_strength); if (event != nullptr) { if (p_pressed != nullptr) { *p_pressed = pressed; @@ -204,6 +215,9 @@ bool InputMap::event_get_action_status(const Ref<InputEvent> &p_event, const Str if (p_strength != nullptr) { *p_strength = strength; } + if (p_raw_strength != nullptr) { + *p_raw_strength = raw_strength; + } return true; } else { return false; @@ -214,7 +228,7 @@ const Map<StringName, InputMap::Action> &InputMap::get_action_map() const { return input_map; } -void InputMap::load_from_globals() { +void InputMap::load_from_project_settings() { input_map.clear(); List<PropertyInfo> pinfo; diff --git a/core/input/input_map.h b/core/input/input_map.h index 548553ed31..1646e7fadb 100644 --- a/core/input/input_map.h +++ b/core/input/input_map.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,7 @@ #define INPUT_MAP_H #include "core/input/input_event.h" -#include "core/object.h" +#include "core/object/class_db.h" class InputMap : public Object { GDCLASS(InputMap, Object); @@ -54,7 +54,7 @@ private: mutable Map<StringName, Action> input_map; - List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed = nullptr, float *p_strength = nullptr) const; + List<Ref<InputEvent>>::Element *_find_event(Action &p_action, const Ref<InputEvent> &p_event, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const; Array _action_get_events(const StringName &p_action); Array _get_actions(); @@ -70,6 +70,7 @@ public: void add_action(const StringName &p_action, float p_deadzone = 0.5); void erase_action(const StringName &p_action); + float action_get_deadzone(const StringName &p_action); void action_set_deadzone(const StringName &p_action, float p_deadzone); void action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event); bool action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event); @@ -78,10 +79,10 @@ public: const List<Ref<InputEvent>> *action_get_events(const StringName &p_action); bool event_is_action(const Ref<InputEvent> &p_event, const StringName &p_action) const; - bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed = nullptr, float *p_strength = nullptr) const; + bool event_get_action_status(const Ref<InputEvent> &p_event, const StringName &p_action, bool *p_pressed = nullptr, float *p_strength = nullptr, float *p_raw_strength = nullptr) const; const Map<StringName, Action> &get_action_map() const; - void load_from_globals(); + void load_from_project_settings(); void load_default(); InputMap(); diff --git a/core/int_types.h b/core/int_types.h deleted file mode 100644 index 71caa2202d..0000000000 --- a/core/int_types.h +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************/ -/* int_types.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef INT_TYPES_H -#define INT_TYPES_H - -#ifdef _MSC_VER - -typedef signed __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef signed __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef signed __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - -#else - -#ifdef NO_STDINT_H -typedef unsigned char uint8_t; -typedef signed char int8_t; -typedef unsigned short uint16_t; -typedef signed short int16_t; -typedef unsigned int uint32_t; -typedef signed int int32_t; -typedef long long int64_t; -typedef unsigned long long uint64_t; -#else -#include <stdint.h> -#endif - -#endif // _MSC_VER - -#endif // INT_TYPES_H diff --git a/core/io/compression.cpp b/core/io/compression.cpp index 7480262835..456023e2a6 100644 --- a/core/io/compression.cpp +++ b/core/io/compression.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,9 @@ #include "compression.h" +#include "core/config/project_settings.h" #include "core/io/zip_io.h" #include "core/os/copymem.h" -#include "core/project_settings.h" #include "thirdparty/misc/fastlz.h" @@ -257,13 +257,13 @@ int Compression::decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_s } while (ret != Z_STREAM_END); // If all done successfully, resize the output if it's larger than the actual output - if (ret == Z_STREAM_END && (unsigned long)p_dst_vect->size() > strm.total_out) { + if ((unsigned long)p_dst_vect->size() > strm.total_out) { p_dst_vect->resize(strm.total_out); } // clean up and return (void)inflateEnd(&strm); - return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; + return Z_OK; } int Compression::zlib_level = Z_DEFAULT_COMPRESSION; diff --git a/core/io/compression.h b/core/io/compression.h index c103fa8eae..cbfed74124 100644 --- a/core/io/compression.h +++ b/core/io/compression.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef COMPRESSION_H #define COMPRESSION_H +#include "core/templates/vector.h" #include "core/typedefs.h" -#include "core/vector.h" class Compression { public: diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index 1af9142317..015c1f0d90 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,7 @@ #include "core/io/file_access_encrypted.h" #include "core/os/keyboard.h" -#include "core/variant_parser.h" +#include "core/variant/variant_parser.h" PackedStringArray ConfigFile::_get_sections() const { List<String> s; @@ -67,7 +67,7 @@ void ConfigFile::set_value(const String &p_section, const String &p_key, const V return; // ? } values[p_section].erase(p_key); - if (values[p_section].empty()) { + if (values[p_section].is_empty()) { values.erase(p_section); } diff --git a/core/io/config_file.h b/core/io/config_file.h index ae06960f02..386d304f07 100644 --- a/core/io/config_file.h +++ b/core/io/config_file.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,10 +31,10 @@ #ifndef CONFIG_FILE_H #define CONFIG_FILE_H -#include "core/ordered_hash_map.h" +#include "core/object/reference.h" #include "core/os/file_access.h" -#include "core/reference.h" -#include "core/variant_parser.h" +#include "core/templates/ordered_hash_map.h" +#include "core/variant/variant_parser.h" class ConfigFile : public Reference { GDCLASS(ConfigFile, Reference); diff --git a/core/io/dtls_server.cpp b/core/io/dtls_server.cpp index e43b1f5385..288b2efe0e 100644 --- a/core/io/dtls_server.cpp +++ b/core/io/dtls_server.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,8 +30,8 @@ #include "dtls_server.h" +#include "core/config/project_settings.h" #include "core/os/file_access.h" -#include "core/project_settings.h" DTLSServer *(*DTLSServer::_create)() = nullptr; bool DTLSServer::available = false; diff --git a/core/io/dtls_server.h b/core/io/dtls_server.h index ae1d3bcd98..92b6caf508 100644 --- a/core/io/dtls_server.h +++ b/core/io/dtls_server.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/file_access_buffered.cpp b/core/io/file_access_buffered.cpp deleted file mode 100644 index 6208f3a4d1..0000000000 --- a/core/io/file_access_buffered.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/*************************************************************************/ -/* file_access_buffered.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "file_access_buffered.h" - -#include "core/error_macros.h" - -Error FileAccessBuffered::set_error(Error p_error) const { - return (last_error = p_error); -} - -void FileAccessBuffered::set_cache_size(int p_size) { - cache_size = p_size; -} - -int FileAccessBuffered::get_cache_size() { - return cache_size; -} - -int FileAccessBuffered::cache_data_left() const { - if (file.offset >= file.size) { - return 0; - } - - if (cache.offset == -1 || file.offset < cache.offset || file.offset >= cache.offset + cache.buffer.size()) { - return read_data_block(file.offset, cache_size); - } - - return cache.buffer.size() - (file.offset - cache.offset); -} - -void FileAccessBuffered::seek(size_t p_position) { - file.offset = p_position; -} - -void FileAccessBuffered::seek_end(int64_t p_position) { - file.offset = file.size + p_position; -} - -size_t FileAccessBuffered::get_position() const { - return file.offset; -} - -size_t FileAccessBuffered::get_len() const { - return file.size; -} - -bool FileAccessBuffered::eof_reached() const { - return file.offset > file.size; -} - -uint8_t FileAccessBuffered::get_8() const { - ERR_FAIL_COND_V_MSG(!file.open, 0, "Can't get data, when file is not opened."); - - uint8_t byte = 0; - if (cache_data_left() >= 1) { - byte = cache.buffer[file.offset - cache.offset]; - } - - ++file.offset; - - return byte; -} - -int FileAccessBuffered::get_buffer(uint8_t *p_dest, int p_length) const { - ERR_FAIL_COND_V_MSG(!file.open, -1, "Can't get buffer, when file is not opened."); - - if (p_length > cache_size) { - int total_read = 0; - - if (!(cache.offset == -1 || file.offset < cache.offset || file.offset >= cache.offset + cache.buffer.size())) { - int size = (cache.buffer.size() - (file.offset - cache.offset)); - size = size - (size % 4); - //const uint8_t* read = cache.buffer.ptr(); - //memcpy(p_dest, read.ptr() + (file.offset - cache.offset), size); - memcpy(p_dest, cache.buffer.ptr() + (file.offset - cache.offset), size); - p_dest += size; - p_length -= size; - file.offset += size; - total_read += size; - } - - int err = read_data_block(file.offset, p_length, p_dest); - if (err >= 0) { - total_read += err; - file.offset += err; - } - - return total_read; - } - - int to_read = p_length; - int total_read = 0; - while (to_read > 0) { - int left = cache_data_left(); - if (left == 0) { - file.offset += to_read; - return total_read; - } - if (left < 0) { - return left; - } - - int r = MIN(left, to_read); - //const uint8_t* read = cache.buffer.ptr(); - //memcpy(p_dest+total_read, &read.ptr()[file.offset - cache.offset], r); - memcpy(p_dest + total_read, cache.buffer.ptr() + (file.offset - cache.offset), r); - - file.offset += r; - total_read += r; - to_read -= r; - } - - return p_length; -} - -bool FileAccessBuffered::is_open() const { - return file.open; -} - -Error FileAccessBuffered::get_error() const { - return last_error; -} diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h deleted file mode 100644 index f22e54e154..0000000000 --- a/core/io/file_access_buffered_fa.h +++ /dev/null @@ -1,139 +0,0 @@ -/*************************************************************************/ -/* file_access_buffered_fa.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef FILE_ACCESS_BUFFERED_FA_H -#define FILE_ACCESS_BUFFERED_FA_H - -#include "core/io/file_access_buffered.h" - -template <class T> -class FileAccessBufferedFA : public FileAccessBuffered { - T f; - - int read_data_block(int p_offset, int p_size, uint8_t *p_dest = 0) const { - ERR_FAIL_COND_V_MSG(!f.is_open(), -1, "Can't read data block when file is not opened."); - - ((T *)&f)->seek(p_offset); - - if (p_dest) { - f.get_buffer(p_dest, p_size); - return p_size; - - } else { - cache.offset = p_offset; - cache.buffer.resize(p_size); - - // on Vector - //uint8_t* write = cache.buffer.ptrw(); - //f.get_buffer(write.ptrw(), p_size); - - // on vector - f.get_buffer(cache.buffer.ptrw(), p_size); - - return p_size; - } - } - - static FileAccess *create() { - return memnew(FileAccessBufferedFA<T>()); - } - -protected: - virtual void _set_access_type(AccessType p_access) { - f._set_access_type(p_access); - FileAccessBuffered::_set_access_type(p_access); - } - -public: - void flush() { - f.flush(); - } - - void store_8(uint8_t p_dest) { - f.store_8(p_dest); - } - - void store_buffer(const uint8_t *p_src, int p_length) { - f.store_buffer(p_src, p_length); - } - - bool file_exists(const String &p_name) { - return f.file_exists(p_name); - } - - Error _open(const String &p_path, int p_mode_flags) { - close(); - - Error ret = f._open(p_path, p_mode_flags); - if (ret != OK) - return ret; - //ERR_FAIL_COND_V( ret != OK, ret ); - - file.size = f.get_len(); - file.offset = 0; - file.open = true; - file.name = p_path; - file.access_flags = p_mode_flags; - - cache.buffer.resize(0); - cache.offset = 0; - - return set_error(OK); - } - - void close() { - f.close(); - - file.offset = 0; - file.size = 0; - file.open = false; - file.name = ""; - - cache.buffer.resize(0); - cache.offset = 0; - set_error(OK); - } - - virtual uint64_t _get_modified_time(const String &p_file) { - return f._get_modified_time(p_file); - } - - virtual uint32_t _get_unix_permissions(const String &p_file) { - return f._get_unix_permissions(p_file); - } - - virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) { - return f._set_unix_permissions(p_file, p_permissions); - } - - FileAccessBufferedFA() {} -}; - -#endif // FILE_ACCESS_BUFFERED_FA_H diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp index 7817ccb773..9ec2b27e88 100644 --- a/core/io/file_access_compressed.cpp +++ b/core/io/file_access_compressed.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "file_access_compressed.h" -#include "core/print_string.h" +#include "core/string/print_string.h" void FileAccessCompressed::configure(const String &p_magic, Compression::Mode p_mode, int p_block_size) { magic = p_magic.ascii().get_data(); @@ -327,14 +327,14 @@ Error FileAccessCompressed::get_error() const { void FileAccessCompressed::flush() { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); - ERR_FAIL_COND_MSG(!writing, "File has not been opened in read mode."); + ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode."); // compressed files keep data in memory till close() } void FileAccessCompressed::store_8(uint8_t p_dest) { ERR_FAIL_COND_MSG(!f, "File must be opened before use."); - ERR_FAIL_COND_MSG(!writing, "File has not been opened in read mode."); + ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode."); WRITE_FIT(1); write_ptr[write_pos++] = p_dest; diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h index 52284b347e..118d05ea57 100644 --- a/core/io/file_access_compressed.h +++ b/core/io/file_access_compressed.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index eb684f457e..8b4c57ce64 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,8 +32,8 @@ #include "core/crypto/crypto_core.h" #include "core/os/copymem.h" -#include "core/print_string.h" -#include "core/variant.h" +#include "core/string/print_string.h" +#include "core/variant/variant.h" #include <stdio.h> @@ -256,7 +256,7 @@ Error FileAccessEncrypted::get_error() const { } void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) { - ERR_FAIL_COND_MSG(!writing, "File has not been opened in read mode."); + ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode."); if (pos < data.size()) { for (int i = 0; i < p_length; i++) { @@ -272,13 +272,13 @@ void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) { } void FileAccessEncrypted::flush() { - ERR_FAIL_COND_MSG(!writing, "File has not been opened in read mode."); + ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode."); // encrypted files keep data in memory till close() } void FileAccessEncrypted::store_8(uint8_t p_dest) { - ERR_FAIL_COND_MSG(!writing, "File has not been opened in read mode."); + ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode."); if (pos < data.size()) { data.write[pos] = p_dest; diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h index fddc6842f3..969052d04f 100644 --- a/core/io/file_access_encrypted.h +++ b/core/io/file_access_encrypted.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,8 +47,8 @@ private: Vector<uint8_t> key; bool writing = false; FileAccess *file = nullptr; - size_t base; - size_t length; + size_t base = 0; + size_t length = 0; Vector<uint8_t> data; mutable int pos = 0; mutable bool eofed = false; diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp index a65ff92a89..04270de77f 100644 --- a/core/io/file_access_memory.cpp +++ b/core/io/file_access_memory.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,10 +30,10 @@ #include "file_access_memory.h" -#include "core/map.h" +#include "core/config/project_settings.h" #include "core/os/copymem.h" #include "core/os/dir_access.h" -#include "core/project_settings.h" +#include "core/templates/map.h" static Map<String, Vector<uint8_t>> *files = nullptr; diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h index 1a9bd3fbbb..0e3b0ad7b1 100644 --- a/core/io/file_access_memory.h +++ b/core/io/file_access_memory.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,8 +35,8 @@ class FileAccessMemory : public FileAccess { uint8_t *data = nullptr; - int length; - mutable int pos; + int length = 0; + mutable int pos = 0; static FileAccess *create(); diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp index 6890740d90..1d9aa846eb 100644 --- a/core/io/file_access_network.cpp +++ b/core/io/file_access_network.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,10 +30,10 @@ #include "file_access_network.h" +#include "core/config/project_settings.h" #include "core/io/ip.h" #include "core/io/marshalls.h" #include "core/os/os.h" -#include "core/project_settings.h" //#define DEBUG_PRINT(m_p) print_line(m_p) //#define DEBUG_TIME(m_what) printf("MS: %s - %lli\n",m_what,OS::get_singleton()->get_ticks_usec()); @@ -350,7 +350,7 @@ void FileAccessNetwork::_queue_page(int p_page) const { if (p_page >= pages.size()) { return; } - if (pages[p_page].buffer.empty() && !pages[p_page].queued) { + if (pages[p_page].buffer.is_empty() && !pages[p_page].queued) { FileAccessNetworkClient *nc = FileAccessNetworkClient::singleton; { MutexLock lock(nc->blockrequest_mutex); @@ -386,7 +386,7 @@ int FileAccessNetwork::get_buffer(uint8_t *p_dst, int p_length) const { if (page != last_page) { buffer_mutex.lock(); - if (pages[page].buffer.empty()) { + if (pages[page].buffer.is_empty()) { waiting_on_page = page; for (int j = 0; j < read_ahead; j++) { _queue_page(page + j); diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h index dc5ce1e883..6aec2869fc 100644 --- a/core/io/file_access_network.h +++ b/core/io/file_access_network.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 8fdbb650d4..faf4fca14f 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #include "file_access_pack.h" #include "core/io/file_access_encrypted.h" -#include "core/script_language.h" +#include "core/object/script_language.h" #include "core/version.h" #include <stdio.h> @@ -89,7 +89,7 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o } String filename = path.get_file(); // Don't add as a file if the path points to a directory - if (!filename.empty()) { + if (!filename.is_empty()) { cd->files.insert(filename); } } @@ -442,8 +442,14 @@ String DirAccessPack::get_drive(int p_drive) { return ""; } -Error DirAccessPack::change_dir(String p_dir) { +PackedData::PackedDir *DirAccessPack::_find_dir(String p_dir) { String nd = p_dir.replace("\\", "/"); + + // Special handling since simplify_path() will forbid it + if (p_dir == "..") { + return current->parent; + } + bool absolute = false; if (nd.begins_with("res://")) { nd = nd.replace_first("res://", ""); @@ -483,13 +489,21 @@ Error DirAccessPack::change_dir(String p_dir) { pd = pd->subdirs[p]; } else { - return ERR_INVALID_PARAMETER; + return nullptr; } } - current = pd; + return pd; +} - return OK; +Error DirAccessPack::change_dir(String p_dir) { + PackedData::PackedDir *pd = _find_dir(p_dir); + if (pd) { + current = pd; + return OK; + } else { + return ERR_INVALID_PARAMETER; + } } String DirAccessPack::get_current_dir(bool p_include_drive) { @@ -507,13 +521,17 @@ String DirAccessPack::get_current_dir(bool p_include_drive) { bool DirAccessPack::file_exists(String p_file) { p_file = fix_path(p_file); - return current->files.has(p_file); + PackedData::PackedDir *pd = _find_dir(p_file.get_base_dir()); + if (!pd) { + return false; + } + return pd->files.has(p_file.get_file()); } bool DirAccessPack::dir_exists(String p_dir) { p_dir = fix_path(p_dir); - return current->subdirs.has(p_dir); + return _find_dir(p_dir) != nullptr; } Error DirAccessPack::make_dir(String p_dir) { diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index d934b0deb5..3c84e6b656 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,11 +31,11 @@ #ifndef FILE_ACCESS_PACK_H #define FILE_ACCESS_PACK_H -#include "core/list.h" -#include "core/map.h" #include "core/os/dir_access.h" #include "core/os/file_access.h" -#include "core/print_string.h" +#include "core/string/print_string.h" +#include "core/templates/list.h" +#include "core/templates/map.h" // Godot's packed file magic header ("GDPC" in ASCII). #define PACK_HEADER_MAGIC 0x43504447 @@ -122,6 +122,9 @@ public: _FORCE_INLINE_ FileAccess *try_open_path(const String &p_path); _FORCE_INLINE_ bool has_path(const String &p_path); + _FORCE_INLINE_ DirAccess *try_open_directory(const String &p_path); + _FORCE_INLINE_ bool has_directory(const String &p_path); + PackedData(); ~PackedData(); }; @@ -199,6 +202,16 @@ bool PackedData::has_path(const String &p_path) { return files.has(PathMD5(p_path.md5_buffer())); } +bool PackedData::has_directory(const String &p_path) { + DirAccess *da = try_open_directory(p_path); + if (da) { + memdelete(da); + return true; + } else { + return false; + } +} + class DirAccessPack : public DirAccess { PackedData::PackedDir *current; @@ -206,6 +219,8 @@ class DirAccessPack : public DirAccess { List<String> list_files; bool cdir = false; + PackedData::PackedDir *_find_dir(String p_dir); + public: virtual Error list_dir_begin(); virtual String get_next(); @@ -235,4 +250,13 @@ public: ~DirAccessPack() {} }; +DirAccess *PackedData::try_open_directory(const String &p_path) { + DirAccess *da = memnew(DirAccessPack()); + if (da->change_dir(p_path) != OK) { + memdelete(da); + da = nullptr; + } + return da; +} + #endif // FILE_ACCESS_PACK_H diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp index ce402fe8ed..01f9337a80 100644 --- a/core/io/file_access_zip.cpp +++ b/core/io/file_access_zip.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -102,7 +102,6 @@ static voidpf godot_alloc(voidpf opaque, uInt items, uInt size) { static void godot_free(voidpf opaque, voidpf address) { memfree(address); } - } // extern "C" void ZipArchive::close_handle(unzFile p_file) const { diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h index c251b3c424..8559f871ce 100644 --- a/core/io/file_access_zip.h +++ b/core/io/file_access_zip.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,7 +34,7 @@ #ifdef MINIZIP_ENABLED #include "core/io/file_access_pack.h" -#include "core/map.h" +#include "core/templates/map.h" #include "thirdparty/minizip/unzip.h" @@ -59,8 +59,6 @@ private: static ZipArchive *instance; - FileAccess::CreateFunc fa_create_func; - public: void close_handle(unzFile p_file) const; unzFile get_file_handle(String p_file) const; diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index a25413b21b..a2fcf074ae 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -109,24 +109,41 @@ Ref<StreamPeer> HTTPClient::get_connection() const { return connection; } +static bool _check_request_url(HTTPClient::Method p_method, const String &p_url) { + switch (p_method) { + case HTTPClient::METHOD_CONNECT: { + // Authority in host:port format, as in RFC7231 + int pos = p_url.find_char(':'); + return 0 < pos && pos < p_url.length() - 1; + } + case HTTPClient::METHOD_OPTIONS: { + if (p_url == "*") { + return true; + } + [[fallthrough]]; + } + default: + // Absolute path or absolute URL + return p_url.begins_with("/") || p_url.begins_with("http://") || p_url.begins_with("https://"); + } +} + Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const Vector<uint8_t> &p_body) { ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(!_check_request_url(p_method, p_url), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA); String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n"; - if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) { - // Don't append the standard ports - request += "Host: " + conn_host + "\r\n"; - } else { - request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n"; - } + bool add_host = true; bool add_clen = p_body.size() > 0; bool add_uagent = true; bool add_accept = true; for (int i = 0; i < p_headers.size(); i++) { request += p_headers[i] + "\r\n"; + if (add_host && p_headers[i].findn("Host:") == 0) { + add_host = false; + } if (add_clen && p_headers[i].findn("Content-Length:") == 0) { add_clen = false; } @@ -137,6 +154,14 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector add_accept = false; } } + if (add_host) { + if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) { + // Don't append the standard ports + request += "Host: " + conn_host + "\r\n"; + } else { + request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n"; + } + } if (add_clen) { request += "Content-Length: " + itos(p_body.size()) + "\r\n"; // Should it add utf8 encoding? @@ -178,22 +203,20 @@ Error HTTPClient::request_raw(Method p_method, const String &p_url, const Vector Error HTTPClient::request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body) { ERR_FAIL_INDEX_V(p_method, METHOD_MAX, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(!_check_request_url(p_method, p_url), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(status != STATUS_CONNECTED, ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(connection.is_null(), ERR_INVALID_DATA); String request = String(_methods[p_method]) + " " + p_url + " HTTP/1.1\r\n"; - if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) { - // Don't append the standard ports - request += "Host: " + conn_host + "\r\n"; - } else { - request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n"; - } + bool add_host = true; bool add_uagent = true; bool add_accept = true; bool add_clen = p_body.length() > 0; for (int i = 0; i < p_headers.size(); i++) { request += p_headers[i] + "\r\n"; + if (add_host && p_headers[i].findn("Host:") == 0) { + add_host = false; + } if (add_clen && p_headers[i].findn("Content-Length:") == 0) { add_clen = false; } @@ -204,6 +227,14 @@ Error HTTPClient::request(Method p_method, const String &p_url, const Vector<Str add_accept = false; } } + if (add_host) { + if ((ssl && conn_port == PORT_HTTPS) || (!ssl && conn_port == PORT_HTTP)) { + // Don't append the standard ports + request += "Host: " + conn_host + "\r\n"; + } else { + request += "Host: " + conn_host + ":" + itos(conn_port) + "\r\n"; + } + } if (add_clen) { request += "Content-Length: " + itos(p_body.utf8().length()) + "\r\n"; // Should it add utf8 encoding? diff --git a/core/io/http_client.h b/core/io/http_client.h index 1dc1f3d76a..ec4b86b26f 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,14 +34,13 @@ #include "core/io/ip.h" #include "core/io/stream_peer.h" #include "core/io/stream_peer_tcp.h" -#include "core/reference.h" +#include "core/object/reference.h" class HTTPClient : public Reference { GDCLASS(HTTPClient, Reference); public: enum ResponseCode { - // 1xx informational RESPONSE_CONTINUE = 100, RESPONSE_SWITCHING_PROTOCOLS = 101, @@ -116,7 +115,6 @@ public: }; enum Method { - METHOD_GET, METHOD_HEAD, METHOD_POST, @@ -131,7 +129,6 @@ public: }; enum Status { - STATUS_DISCONNECTED, STATUS_RESOLVING, // Resolving hostname (if passed a hostname) STATUS_CANT_RESOLVE, @@ -150,7 +147,6 @@ private: static const int HOST_MIN_LEN = 4; enum Port { - PORT_HTTP = 80, PORT_HTTPS = 443, @@ -182,7 +178,8 @@ private: int response_num = 0; Vector<String> response_headers; - int read_chunk_size = 4096; + // 64 KiB by default (favors fast download speeds at the cost of memory usage). + int read_chunk_size = 65536; Error _get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received); diff --git a/core/image.cpp b/core/io/image.cpp index b8a443eed2..986c29b539 100644 --- a/core/image.cpp +++ b/core/io/image.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,13 +30,13 @@ #include "image.h" -#include "core/error_macros.h" -#include "core/hash_map.h" +#include "core/error/error_macros.h" #include "core/io/image_loader.h" #include "core/io/resource_loader.h" #include "core/math/math_funcs.h" #include "core/os/copymem.h" -#include "core/print_string.h" +#include "core/string/print_string.h" +#include "core/templates/hash_map.h" #include <stdio.h> @@ -66,10 +66,10 @@ const char *Image::format_names[Image::FORMAT_MAX] = { "BPTC_RGBA", "BPTC_RGBF", "BPTC_RGBFU", - "PVRTC2", //pvrtc - "PVRTC2A", - "PVRTC4", - "PVRTC4A", + "PVRTC1_2", //pvrtc + "PVRTC1_2A", + "PVRTC1_4", + "PVRTC1_4A", "ETC", //etc1 "ETC2_R11", //etc2 "ETC2_R11S", //signed", NOT srgb. @@ -80,7 +80,6 @@ const char *Image::format_names[Image::FORMAT_MAX] = { "ETC2_RGB8A1", "ETC2_RA_AS_RG", "FORMAT_DXT5_RA_AS_RG", - }; SavePNGFunc Image::save_png_func = nullptr; @@ -156,13 +155,13 @@ int Image::get_format_pixel_size(Format p_format) { return 1; //float / case FORMAT_BPTC_RGBFU: return 1; //unsigned float - case FORMAT_PVRTC2: + case FORMAT_PVRTC1_2: return 1; //pvrtc - case FORMAT_PVRTC2A: + case FORMAT_PVRTC1_2A: return 1; - case FORMAT_PVRTC4: + case FORMAT_PVRTC1_4: return 1; - case FORMAT_PVRTC4A: + case FORMAT_PVRTC1_4A: return 1; case FORMAT_ETC: return 1; //etc1 @@ -201,13 +200,13 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { r_w = 4; r_h = 4; } break; - case FORMAT_PVRTC2: - case FORMAT_PVRTC2A: { + case FORMAT_PVRTC1_2: + case FORMAT_PVRTC1_2A: { r_w = 16; r_h = 8; } break; - case FORMAT_PVRTC4A: - case FORMAT_PVRTC4: { + case FORMAT_PVRTC1_4A: + case FORMAT_PVRTC1_4: { r_w = 8; r_h = 8; } break; @@ -243,9 +242,9 @@ void Image::get_format_min_pixel_size(Format p_format, int &r_w, int &r_h) { } int Image::get_format_pixel_rshift(Format p_format) { - if (p_format == FORMAT_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_PVRTC4 || p_format == FORMAT_PVRTC4A || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) { + if (p_format == FORMAT_DXT1 || p_format == FORMAT_RGTC_R || p_format == FORMAT_PVRTC1_4 || p_format == FORMAT_PVRTC1_4A || p_format == FORMAT_ETC || p_format == FORMAT_ETC2_R11 || p_format == FORMAT_ETC2_R11S || p_format == FORMAT_ETC2_RGB8 || p_format == FORMAT_ETC2_RGB8A1) { return 1; - } else if (p_format == FORMAT_PVRTC2 || p_format == FORMAT_PVRTC2A) { + } else if (p_format == FORMAT_PVRTC1_2 || p_format == FORMAT_PVRTC1_2A) { return 2; } else { return 0; @@ -262,12 +261,12 @@ int Image::get_format_block_size(Format p_format) { return 4; } - case FORMAT_PVRTC2: - case FORMAT_PVRTC2A: { + case FORMAT_PVRTC1_2: + case FORMAT_PVRTC1_2A: { return 4; } - case FORMAT_PVRTC4A: - case FORMAT_PVRTC4: { + case FORMAT_PVRTC1_4A: + case FORMAT_PVRTC1_4: { return 4; } case FORMAT_ETC: { @@ -376,7 +375,7 @@ Image::Image3DValidateError Image::validate_3d_image(Image::Format p_format, int if (idx >= p_images.size()) { return VALIDATE_3D_ERR_MISSING_IMAGES; } - if (p_images[idx].is_null() || p_images[idx]->empty()) { + if (p_images[idx].is_null() || p_images[idx]->is_empty()) { return VALIDATE_3D_ERR_IMAGE_EMPTY; } if (p_images[idx]->get_format() != p_format) { @@ -994,7 +993,7 @@ bool Image::is_size_po2() const { return uint32_t(width) == next_power_of_2(width) && uint32_t(height) == next_power_of_2(height); } -void Image::resize_to_po2(bool p_square) { +void Image::resize_to_po2(bool p_square, Interpolation p_interpolation) { ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats."); int w = next_power_of_2(width); @@ -1009,7 +1008,7 @@ void Image::resize_to_po2(bool p_square) { } } - resize(w, h); + resize(w, h, p_interpolation); } void Image::resize(int p_width, int p_height, Interpolation p_interpolation) { @@ -1754,10 +1753,10 @@ Error Image::generate_mipmaps(bool p_renormalize) { Error Image::generate_mipmap_roughness(RoughnessChannel p_roughness_channel, const Ref<Image> &p_normal_map) { Vector<double> normal_sat_vec; //summed area table - double *normal_sat = nullptr; //summed area table for normalmap + double *normal_sat = nullptr; //summed area table for normal map int normal_w = 0, normal_h = 0; - ERR_FAIL_COND_V_MSG(p_normal_map.is_null() || p_normal_map->empty(), ERR_INVALID_PARAMETER, "Must provide a valid normalmap for roughness mipmaps"); + ERR_FAIL_COND_V_MSG(p_normal_map.is_null() || p_normal_map->is_empty(), ERR_INVALID_PARAMETER, "Must provide a valid normal map for roughness mipmaps"); Ref<Image> nm = p_normal_map->duplicate(); if (nm->is_compressed()) { @@ -1951,7 +1950,7 @@ void Image::clear_mipmaps() { return; } - if (empty()) { + if (is_empty()) { return; } @@ -1962,7 +1961,7 @@ void Image::clear_mipmaps() { mipmaps = false; } -bool Image::empty() const { +bool Image::is_empty() const { return (data.size() == 0); } @@ -2217,8 +2216,8 @@ bool Image::is_invisible() const { } break; - case FORMAT_PVRTC2A: - case FORMAT_PVRTC4A: + case FORMAT_PVRTC1_2A: + case FORMAT_PVRTC1_4A: case FORMAT_DXT3: case FORMAT_DXT5: { detected = true; @@ -2259,8 +2258,8 @@ Image::AlphaMode Image::detect_alpha() const { } } break; - case FORMAT_PVRTC2A: - case FORMAT_PVRTC4A: + case FORMAT_PVRTC1_2A: + case FORMAT_PVRTC1_4A: case FORMAT_DXT3: case FORMAT_DXT5: { detected = true; @@ -2356,7 +2355,7 @@ Error Image::decompress() { _image_decompress_bc(this); } else if (format >= FORMAT_BPTC_RGBA && format <= FORMAT_BPTC_RGBFU && _image_decompress_bptc) { _image_decompress_bptc(this); - } else if (format >= FORMAT_PVRTC2 && format <= FORMAT_PVRTC4A && _image_decompress_pvrtc) { + } else if (format >= FORMAT_PVRTC1_2 && format <= FORMAT_PVRTC1_4A && _image_decompress_pvrtc) { _image_decompress_pvrtc(this); } else if (format == FORMAT_ETC && _image_decompress_etc1) { _image_decompress_etc1(this); @@ -2378,13 +2377,9 @@ Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels ERR_FAIL_COND_V(!_image_compress_bc_func, ERR_UNAVAILABLE); _image_compress_bc_func(this, p_lossy_quality, p_channels); } break; - case COMPRESS_PVRTC2: { - ERR_FAIL_COND_V(!_image_compress_pvrtc2_func, ERR_UNAVAILABLE); - _image_compress_pvrtc2_func(this); - } break; - case COMPRESS_PVRTC4: { - ERR_FAIL_COND_V(!_image_compress_pvrtc4_func, ERR_UNAVAILABLE); - _image_compress_pvrtc4_func(this); + case COMPRESS_PVRTC1_4: { + ERR_FAIL_COND_V(!_image_compress_pvrtc1_4bpp_func, ERR_UNAVAILABLE); + _image_compress_pvrtc1_4bpp_func(this); } break; case COMPRESS_ETC: { ERR_FAIL_COND_V(!_image_compress_etc1_func, ERR_UNAVAILABLE); @@ -2485,7 +2480,7 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po ERR_FAIL_COND(format != p_src->format); ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot blit_rect in compressed or custom image formats."); - Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect); + Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect); if (p_dest.x < 0) { clipped_src_rect.position.x = ABS(p_dest.x); @@ -2499,7 +2494,7 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po } Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); - Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); + Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); uint8_t *wp = data.ptrw(); uint8_t *dst_data_ptr = wp; @@ -2540,7 +2535,7 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height."); ERR_FAIL_COND(format != p_src->format); - Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect); + Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect); if (p_dest.x < 0) { clipped_src_rect.position.x = ABS(p_dest.x); @@ -2554,7 +2549,7 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co } Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); - Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); + Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); uint8_t *wp = data.ptrw(); uint8_t *dst_data_ptr = wp; @@ -2594,7 +2589,7 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P ERR_FAIL_COND(srcdsize == 0); ERR_FAIL_COND(format != p_src->format); - Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect); + Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect); if (p_dest.x < 0) { clipped_src_rect.position.x = ABS(p_dest.x); @@ -2608,7 +2603,7 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P } Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); - Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); + Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); Ref<Image> img = p_src; @@ -2643,7 +2638,7 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height."); ERR_FAIL_COND(format != p_src->format); - Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).clip(p_src_rect); + Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect); if (p_dest.x < 0) { clipped_src_rect.position.x = ABS(p_dest.x); @@ -2657,7 +2652,7 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c } Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y)); - Rect2i dest_rect = Rect2i(0, 0, width, height).clip(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); + Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size)); Ref<Image> img = p_src; Ref<Image> msk = p_mask; @@ -2711,11 +2706,11 @@ ImageMemLoadFunc Image::_png_mem_loader_func = nullptr; ImageMemLoadFunc Image::_jpg_mem_loader_func = nullptr; ImageMemLoadFunc Image::_webp_mem_loader_func = nullptr; ImageMemLoadFunc Image::_tga_mem_loader_func = nullptr; +ImageMemLoadFunc Image::_bmp_mem_loader_func = nullptr; void (*Image::_image_compress_bc_func)(Image *, float, Image::UsedChannels) = nullptr; void (*Image::_image_compress_bptc_func)(Image *, float, Image::UsedChannels) = nullptr; -void (*Image::_image_compress_pvrtc2_func)(Image *) = nullptr; -void (*Image::_image_compress_pvrtc4_func)(Image *) = nullptr; +void (*Image::_image_compress_pvrtc1_4bpp_func)(Image *) = nullptr; void (*Image::_image_compress_etc1_func)(Image *, float) = nullptr; void (*Image::_image_compress_etc2_func)(Image *, float, Image::UsedChannels) = nullptr; void (*Image::_image_decompress_pvrtc)(Image *) = nullptr; @@ -2766,8 +2761,8 @@ Dictionary Image::_get_data() const { return d; } -Color Image::get_pixelv(const Point2 &p_src) const { - return get_pixel(p_src.x, p_src.y); +Color Image::get_pixelv(const Point2i &p_point) const { + return get_pixel(p_point.x, p_point.y); } Color Image::_get_color_at_ofs(const uint8_t *ptr, uint32_t ofs) const { @@ -2976,8 +2971,8 @@ Color Image::get_pixel(int p_x, int p_y) const { return _get_color_at_ofs(data.ptr(), ofs); } -void Image::set_pixelv(const Point2 &p_dst, const Color &p_color) { - set_pixel(p_dst.x, p_dst.y, p_color); +void Image::set_pixelv(const Point2i &p_point, const Color &p_color) { + set_pixel(p_point.x, p_point.y, p_color); } void Image::set_pixel(int p_x, int p_y, const Color &p_color) { @@ -3082,7 +3077,7 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("get_mipmap_offset", "mipmap"), &Image::get_mipmap_offset); - ClassDB::bind_method(D_METHOD("resize_to_po2", "square"), &Image::resize_to_po2, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("resize_to_po2", "square", "interpolation"), &Image::resize_to_po2, DEFVAL(false), DEFVAL(INTERPOLATE_BILINEAR)); ClassDB::bind_method(D_METHOD("resize", "width", "height", "interpolation"), &Image::resize, DEFVAL(INTERPOLATE_BILINEAR)); ClassDB::bind_method(D_METHOD("shrink_x2"), &Image::shrink_x2); @@ -3095,7 +3090,7 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("create", "width", "height", "use_mipmaps", "format"), &Image::_create_empty); ClassDB::bind_method(D_METHOD("create_from_data", "width", "height", "use_mipmaps", "format", "data"), &Image::_create_from_data); - ClassDB::bind_method(D_METHOD("is_empty"), &Image::empty); + ClassDB::bind_method(D_METHOD("is_empty"), &Image::is_empty); ClassDB::bind_method(D_METHOD("load", "path"), &Image::load); ClassDB::bind_method(D_METHOD("save_png", "path"), &Image::save_png); @@ -3114,9 +3109,9 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("fix_alpha_edges"), &Image::fix_alpha_edges); ClassDB::bind_method(D_METHOD("premultiply_alpha"), &Image::premultiply_alpha); ClassDB::bind_method(D_METHOD("srgb_to_linear"), &Image::srgb_to_linear); - ClassDB::bind_method(D_METHOD("normalmap_to_xy"), &Image::normalmap_to_xy); + ClassDB::bind_method(D_METHOD("normal_map_to_xy"), &Image::normal_map_to_xy); ClassDB::bind_method(D_METHOD("rgbe_to_srgb"), &Image::rgbe_to_srgb); - ClassDB::bind_method(D_METHOD("bumpmap_to_normalmap", "bump_scale"), &Image::bumpmap_to_normalmap, DEFVAL(1.0)); + ClassDB::bind_method(D_METHOD("bump_map_to_normal_map", "bump_scale"), &Image::bump_map_to_normal_map, DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("blit_rect", "src", "src_rect", "dst"), &Image::blit_rect); ClassDB::bind_method(D_METHOD("blit_rect_mask", "src", "mask", "src_rect", "dst"), &Image::blit_rect_mask); @@ -3132,15 +3127,16 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_data", "data"), &Image::_set_data); ClassDB::bind_method(D_METHOD("_get_data"), &Image::_get_data); - ClassDB::bind_method(D_METHOD("get_pixelv", "src"), &Image::get_pixelv); + ClassDB::bind_method(D_METHOD("get_pixelv", "point"), &Image::get_pixelv); ClassDB::bind_method(D_METHOD("get_pixel", "x", "y"), &Image::get_pixel); - ClassDB::bind_method(D_METHOD("set_pixelv", "dst", "color"), &Image::set_pixelv); + ClassDB::bind_method(D_METHOD("set_pixelv", "point", "color"), &Image::set_pixelv); ClassDB::bind_method(D_METHOD("set_pixel", "x", "y", "color"), &Image::set_pixel); ClassDB::bind_method(D_METHOD("load_png_from_buffer", "buffer"), &Image::load_png_from_buffer); ClassDB::bind_method(D_METHOD("load_jpg_from_buffer", "buffer"), &Image::load_jpg_from_buffer); ClassDB::bind_method(D_METHOD("load_webp_from_buffer", "buffer"), &Image::load_webp_from_buffer); ClassDB::bind_method(D_METHOD("load_tga_from_buffer", "buffer"), &Image::load_tga_from_buffer); + ClassDB::bind_method(D_METHOD("load_bmp_from_buffer", "buffer"), &Image::load_bmp_from_buffer); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "_set_data", "_get_data"); @@ -3172,10 +3168,10 @@ void Image::_bind_methods() { BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBA); //btpc bc6h BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBF); //float / BIND_ENUM_CONSTANT(FORMAT_BPTC_RGBFU); //unsigned float - BIND_ENUM_CONSTANT(FORMAT_PVRTC2); //pvrtc - BIND_ENUM_CONSTANT(FORMAT_PVRTC2A); - BIND_ENUM_CONSTANT(FORMAT_PVRTC4); - BIND_ENUM_CONSTANT(FORMAT_PVRTC4A); + BIND_ENUM_CONSTANT(FORMAT_PVRTC1_2); //pvrtc + BIND_ENUM_CONSTANT(FORMAT_PVRTC1_2A); + BIND_ENUM_CONSTANT(FORMAT_PVRTC1_4); + BIND_ENUM_CONSTANT(FORMAT_PVRTC1_4A); BIND_ENUM_CONSTANT(FORMAT_ETC); //etc1 BIND_ENUM_CONSTANT(FORMAT_ETC2_R11); //etc2 BIND_ENUM_CONSTANT(FORMAT_ETC2_R11S); //signed ); NOT srgb. @@ -3199,10 +3195,10 @@ void Image::_bind_methods() { BIND_ENUM_CONSTANT(ALPHA_BLEND); BIND_ENUM_CONSTANT(COMPRESS_S3TC); - BIND_ENUM_CONSTANT(COMPRESS_PVRTC2); - BIND_ENUM_CONSTANT(COMPRESS_PVRTC4); + BIND_ENUM_CONSTANT(COMPRESS_PVRTC1_4); BIND_ENUM_CONSTANT(COMPRESS_ETC); BIND_ENUM_CONSTANT(COMPRESS_ETC2); + BIND_ENUM_CONSTANT(COMPRESS_BPTC); BIND_ENUM_CONSTANT(USED_CHANNELS_L); BIND_ENUM_CONSTANT(USED_CHANNELS_LA); @@ -3224,7 +3220,7 @@ void Image::set_compress_bptc_func(void (*p_compress_func)(Image *, float, UsedC _image_compress_bptc_func = p_compress_func; } -void Image::normalmap_to_xy() { +void Image::normal_map_to_xy() { convert(Image::FORMAT_RGBA8); { @@ -3289,7 +3285,7 @@ Ref<Image> Image::get_image_from_mipmap(int p_mipamp) const { return image; } -void Image::bumpmap_to_normalmap(float bump_scale) { +void Image::bump_map_to_normal_map(float bump_scale) { ERR_FAIL_COND(!_can_modify(format)); convert(Image::FORMAT_RF); @@ -3473,10 +3469,21 @@ Error Image::load_webp_from_buffer(const Vector<uint8_t> &p_array) { } Error Image::load_tga_from_buffer(const Vector<uint8_t> &p_array) { - ERR_FAIL_NULL_V_MSG(_tga_mem_loader_func, ERR_UNAVAILABLE, "TGA module was not installed."); + ERR_FAIL_NULL_V_MSG( + _tga_mem_loader_func, + ERR_UNAVAILABLE, + "The TGA module isn't enabled. Recompile the Godot editor or export template binary with the `module_tga_enabled=yes` SCons option."); return _load_from_buffer(p_array, _tga_mem_loader_func); } +Error Image::load_bmp_from_buffer(const Vector<uint8_t> &p_array) { + ERR_FAIL_NULL_V_MSG( + _bmp_mem_loader_func, + ERR_UNAVAILABLE, + "The BMP module isn't enabled. Recompile the Godot editor or export template binary with the `module_bmp_enabled=yes` SCons option."); + return _load_from_buffer(p_array, _bmp_mem_loader_func); +} + void Image::convert_rg_to_ra_rgba8() { ERR_FAIL_COND(format != FORMAT_RGBA8); ERR_FAIL_COND(!data.size()); @@ -3578,7 +3585,7 @@ Image::Image(const uint8_t *p_mem_png_jpg, int p_len) { copy_internals_from(_png_mem_loader_func(p_mem_png_jpg, p_len)); } - if (empty() && _jpg_mem_loader_func) { + if (is_empty() && _jpg_mem_loader_func) { copy_internals_from(_jpg_mem_loader_func(p_mem_png_jpg, p_len)); } } diff --git a/core/image.h b/core/io/image.h index 06794c7fed..b894be7df4 100644 --- a/core/image.h +++ b/core/io/image.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +31,9 @@ #ifndef IMAGE_H #define IMAGE_H -#include "core/color.h" +#include "core/io/resource.h" +#include "core/math/color.h" #include "core/math/rect2.h" -#include "core/resource.h" /** * @author Juan Linietsky <reduzio@gmail.com> @@ -66,7 +66,6 @@ public: }; enum Format { - FORMAT_L8, //luminance FORMAT_LA8, //luminance-alpha FORMAT_R8, @@ -92,10 +91,10 @@ public: FORMAT_BPTC_RGBA, //btpc bc7 FORMAT_BPTC_RGBF, //float bc6h FORMAT_BPTC_RGBFU, //unsigned float bc6hu - FORMAT_PVRTC2, //pvrtc - FORMAT_PVRTC2A, - FORMAT_PVRTC4, - FORMAT_PVRTC4A, + FORMAT_PVRTC1_2, //pvrtc1 + FORMAT_PVRTC1_2A, + FORMAT_PVRTC1_4, + FORMAT_PVRTC1_4A, FORMAT_ETC, //etc1 FORMAT_ETC2_R11, //etc2 FORMAT_ETC2_R11S, //signed, NOT srgb. @@ -111,7 +110,6 @@ public: static const char *format_names[FORMAT_MAX]; enum Interpolation { - INTERPOLATE_NEAREST, INTERPOLATE_BILINEAR, INTERPOLATE_CUBIC, @@ -136,11 +134,11 @@ public: static ImageMemLoadFunc _jpg_mem_loader_func; static ImageMemLoadFunc _webp_mem_loader_func; static ImageMemLoadFunc _tga_mem_loader_func; + static ImageMemLoadFunc _bmp_mem_loader_func; static void (*_image_compress_bc_func)(Image *, float, UsedChannels p_channels); static void (*_image_compress_bptc_func)(Image *, float p_lossy_quality, UsedChannels p_channels); - static void (*_image_compress_pvrtc2_func)(Image *); - static void (*_image_compress_pvrtc4_func)(Image *); + static void (*_image_compress_pvrtc1_4bpp_func)(Image *); static void (*_image_compress_etc1_func)(Image *, float); static void (*_image_compress_etc2_func)(Image *, float, UsedChannels p_channels); @@ -246,7 +244,7 @@ public: /** * Resize the image, using the preferred interpolation method. */ - void resize_to_po2(bool p_square = false); + void resize_to_po2(bool p_square = false, Interpolation p_interpolation = INTERPOLATE_BILINEAR); void resize(int p_width, int p_height, Interpolation p_interpolation = INTERPOLATE_BILINEAR); void shrink_x2(); bool is_size_po2() const; @@ -287,7 +285,7 @@ public: /** * returns true when the image is empty (0,0) in size */ - bool empty() const; + bool is_empty() const; Vector<uint8_t> get_data() const; @@ -333,11 +331,10 @@ public: enum CompressMode { COMPRESS_S3TC, - COMPRESS_PVRTC2, - COMPRESS_PVRTC4, + COMPRESS_PVRTC1_4, COMPRESS_ETC, COMPRESS_ETC2, - COMPRESS_BPTC + COMPRESS_BPTC, }; enum CompressSource { COMPRESS_SOURCE_GENERIC, @@ -353,10 +350,10 @@ public: void fix_alpha_edges(); void premultiply_alpha(); void srgb_to_linear(); - void normalmap_to_xy(); + void normal_map_to_xy(); Ref<Image> rgbe_to_srgb(); Ref<Image> get_image_from_mipmap(int p_mipamp) const; - void bumpmap_to_normalmap(float bump_scale = 1.0); + void bump_map_to_normal_map(float bump_scale = 1.0); void blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest); void blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest); @@ -375,6 +372,7 @@ public: Error load_jpg_from_buffer(const Vector<uint8_t> &p_array); Error load_webp_from_buffer(const Vector<uint8_t> &p_array); Error load_tga_from_buffer(const Vector<uint8_t> &p_array); + Error load_bmp_from_buffer(const Vector<uint8_t> &p_array); void convert_rg_to_ra_rgba8(); void convert_ra_rgba8_to_rg(); @@ -387,9 +385,9 @@ public: UsedChannels detect_used_channels(CompressSource p_source = COMPRESS_SOURCE_GENERIC); void optimize_channels(); - Color get_pixelv(const Point2 &p_src) const; + Color get_pixelv(const Point2i &p_point) const; Color get_pixel(int p_x, int p_y) const; - void set_pixelv(const Point2 &p_dst, const Color &p_color); + void set_pixelv(const Point2i &p_point, const Color &p_color); void set_pixel(int p_x, int p_y, const Color &p_color); void set_as_black(); diff --git a/core/io/image_loader.cpp b/core/io/image_loader.cpp index b1e92eb87f..8ca1cb3beb 100644 --- a/core/io/image_loader.cpp +++ b/core/io/image_loader.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "image_loader.h" -#include "core/print_string.h" +#include "core/string/print_string.h" bool ImageFormatLoader::recognize(const String &p_extension) const { List<String> extensions; diff --git a/core/io/image_loader.h b/core/io/image_loader.h index 9682f144c7..bf67e1486f 100644 --- a/core/io/image_loader.h +++ b/core/io/image_loader.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,11 +31,11 @@ #ifndef IMAGE_LOADER_H #define IMAGE_LOADER_H -#include "core/image.h" +#include "core/io/image.h" #include "core/io/resource_loader.h" -#include "core/list.h" #include "core/os/file_access.h" -#include "core/ustring.h" +#include "core/string/ustring.h" +#include "core/templates/list.h" class ImageLoader; diff --git a/core/io/ip.cpp b/core/io/ip.cpp index 24b8ec7cc1..6fb812e78d 100644 --- a/core/io/ip.cpp +++ b/core/io/ip.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,9 @@ #include "ip.h" -#include "core/hash_map.h" #include "core/os/semaphore.h" #include "core/os/thread.h" +#include "core/templates/hash_map.h" VARIANT_ENUM_CAST(IP::ResolverStatus); @@ -189,7 +189,7 @@ void IP::erase_resolve_item(ResolverID p_id) { void IP::clear_cache(const String &p_hostname) { MutexLock lock(resolver->mutex); - if (p_hostname.empty()) { + if (p_hostname.is_empty()) { resolver->cache.clear(); } else { resolver->cache.erase(_IP_ResolverPrivate::get_cache_key(p_hostname, IP::TYPE_NONE)); diff --git a/core/io/ip.h b/core/io/ip.h index d434d02f9b..ae080b8e26 100644 --- a/core/io/ip.h +++ b/core/io/ip.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -42,7 +42,6 @@ class IP : public Object { public: enum ResolverStatus { - RESOLVER_STATUS_NONE, RESOLVER_STATUS_WAITING, RESOLVER_STATUS_DONE, @@ -50,7 +49,6 @@ public: }; enum Type { - TYPE_NONE = 0, TYPE_IPV4 = 1, TYPE_IPV6 = 2, diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index d0fb63b958..5f98eb69e8 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,6 @@ #include "ip_address.h" /* IP_Address::operator Variant() const { - return operator String(); }*/ diff --git a/core/io/ip_address.h b/core/io/ip_address.h index 2f8f83503e..49bf83d72f 100644 --- a/core/io/ip_address.h +++ b/core/io/ip_address.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef IP_ADDRESS_H #define IP_ADDRESS_H -#include "core/ustring.h" +#include "core/string/ustring.h" struct IP_Address { private: diff --git a/core/io/json.cpp b/core/io/json.cpp index 1b89d966fd..bc4527869b 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "json.h" -#include "core/print_string.h" +#include "core/string/print_string.h" const char *JSON::tk_name[TK_MAX] = { "'{'", @@ -47,7 +47,7 @@ const char *JSON::tk_name[TK_MAX] = { static String _make_indent(const String &p_indent, int p_size) { String indent_text = ""; - if (!p_indent.empty()) { + if (!p_indent.is_empty()) { for (int i = 0; i < p_size; i++) { indent_text += p_indent; } @@ -59,7 +59,7 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_ String colon = ":"; String end_statement = ""; - if (!p_indent.empty()) { + if (!p_indent.is_empty()) { colon += " "; end_statement += "\n"; } @@ -455,3 +455,35 @@ Error JSON::parse(const String &p_json, Variant &r_ret, String &r_err_str, int & return err; } + +Error JSONParser::parse_string(const String &p_json_string) { + return JSON::parse(p_json_string, data, err_text, err_line); +} +String JSONParser::get_error_text() const { + return err_text; +} +int JSONParser::get_error_line() const { + return err_line; +} +Variant JSONParser::get_data() const { + return data; +} + +Error JSONParser::decode_data(const Variant &p_data, const String &p_indent, bool p_sort_keys) { + string = JSON::print(p_data, p_indent, p_sort_keys); + data = p_data; + return OK; +} + +String JSONParser::get_string() const { + return string; +} + +void JSONParser::_bind_methods() { + ClassDB::bind_method(D_METHOD("parse_string", "json_string"), &JSONParser::parse_string); + ClassDB::bind_method(D_METHOD("get_error_text"), &JSONParser::get_error_text); + ClassDB::bind_method(D_METHOD("get_error_line"), &JSONParser::get_error_line); + ClassDB::bind_method(D_METHOD("get_data"), &JSONParser::get_data); + ClassDB::bind_method(D_METHOD("decode_data", "data", "indent", "sort_keys"), &JSONParser::decode_data, DEFVAL(""), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("get_string"), &JSONParser::get_string); +} diff --git a/core/io/json.h b/core/io/json.h index 9122228163..537477666e 100644 --- a/core/io/json.h +++ b/core/io/json.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef JSON_H #define JSON_H -#include "core/variant.h" - +#include "core/object/reference.h" +#include "core/variant/variant.h" class JSON { enum TokenType { TK_CURLY_BRACKET_OPEN, @@ -49,7 +49,6 @@ class JSON { }; enum Expecting { - EXPECT_OBJECT, EXPECT_OBJECT_KEY, EXPECT_COLON, @@ -75,4 +74,25 @@ public: static Error parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line); }; +class JSONParser : public Reference { + GDCLASS(JSONParser, Reference); + + Variant data; + String string; + String err_text; + int err_line = 0; + +protected: + static void _bind_methods(); + +public: + Error parse_string(const String &p_json_string); + String get_error_text() const; + int get_error_line() const; + Variant get_data() const; + + Error decode_data(const Variant &p_data, const String &p_indent = "", bool p_sort_keys = true); + String get_string() const; +}; + #endif // JSON_H diff --git a/core/io/logger.cpp b/core/io/logger.cpp index 886e5695b1..da200f5717 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,10 @@ #include "logger.h" +#include "core/config/project_settings.h" #include "core/os/dir_access.h" #include "core/os/os.h" -#include "core/print_string.h" +#include "core/string/print_string.h" #if defined(MINGW_ENABLED) || defined(_MSC_VER) #define sprintf sprintf_s @@ -152,7 +153,7 @@ void RotatedFileLogger::rotate_file() { char timestamp[21]; OS::Date date = OS::get_singleton()->get_date(); OS::Time time = OS::get_singleton()->get_time(); - sprintf(timestamp, "_%04d-%02d-%02d_%02d-%02d-%02d", date.year, date.month, date.day, time.hour, time.min, time.sec); + sprintf(timestamp, "_%04d-%02d-%02d_%02d.%02d.%02d", date.year, date.month, date.day, time.hour, time.min, time.sec); String backup_name = base_path.get_basename() + timestamp; if (base_path.get_extension() != String()) { @@ -201,15 +202,14 @@ void RotatedFileLogger::logv(const char *p_format, va_list p_list, bool p_err) { } va_end(list_copy); file->store_buffer((uint8_t *)buf, len); + if (len >= static_buf_size) { Memory::free_static(buf); } -#ifdef DEBUG_ENABLED - const bool need_flush = true; -#else - bool need_flush = p_err; -#endif - if (need_flush) { + + if (p_err || GLOBAL_GET("application/run/flush_stdout_on_print")) { + // Don't always flush when printing stdout to avoid performance + // issues when `print()` is spammed in release builds. file->flush(); } } @@ -228,9 +228,11 @@ void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) { vfprintf(stderr, p_format, p_list); } else { vprintf(p_format, p_list); -#ifdef DEBUG_ENABLED - fflush(stdout); -#endif + if (GLOBAL_GET("application/run/flush_stdout_on_print")) { + // Don't always flush when printing stdout to avoid performance + // issues when `print()` is spammed in release builds. + fflush(stdout); + } } } diff --git a/core/io/logger.h b/core/io/logger.h index 277be9ed35..b8e615b436 100644 --- a/core/io/logger.h +++ b/core/io/logger.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,8 +32,8 @@ #define LOGGER_H #include "core/os/file_access.h" -#include "core/ustring.h" -#include "core/vector.h" +#include "core/string/ustring.h" +#include "core/templates/vector.h" #include <stdarg.h> diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index eb39b1433f..218a612da2 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,9 @@ #include "marshalls.h" +#include "core/object/reference.h" #include "core/os/keyboard.h" -#include "core/print_string.h" -#include "core/reference.h" +#include "core/string/print_string.h" #include <limits.h> #include <stdio.h> @@ -420,7 +420,7 @@ Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int } } break; - case Variant::_RID: { + case Variant::RID: { r_variant = RID(); } break; case Variant::OBJECT: { @@ -1003,10 +1003,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } } break; - case Variant::STRING: { - _encode_string(p_variant, buf, r_len); - - } break; + case Variant::STRING: case Variant::STRING_NAME: { _encode_string(p_variant, buf, r_len); @@ -1172,7 +1169,7 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo r_len += 4 * 4; } break; - case Variant::_RID: { + case Variant::RID: { } break; case Variant::CALLABLE: { } break; diff --git a/core/io/marshalls.h b/core/io/marshalls.h index c8ed497528..cc0e9ba301 100644 --- a/core/io/marshalls.h +++ b/core/io/marshalls.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +31,9 @@ #ifndef MARSHALLS_H #define MARSHALLS_H -#include "core/reference.h" +#include "core/object/reference.h" #include "core/typedefs.h" -#include "core/variant.h" +#include "core/variant/variant.h" /** * Miscellaneous helpers for marshalling data types, and encoding diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index 2f17d9e746..6b550e69c8 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -142,6 +142,10 @@ void MultiplayerAPI::set_root_node(Node *p_node) { root_node = p_node; } +Node *MultiplayerAPI::get_root_node() { + return root_node; +} + void MultiplayerAPI::set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_peer) { if (p_peer == network_peer) { return; // Nothing to do @@ -1202,6 +1206,7 @@ bool MultiplayerAPI::is_object_decoding_allowed() const { void MultiplayerAPI::_bind_methods() { ClassDB::bind_method(D_METHOD("set_root_node", "node"), &MultiplayerAPI::set_root_node); + ClassDB::bind_method(D_METHOD("get_root_node"), &MultiplayerAPI::get_root_node); ClassDB::bind_method(D_METHOD("send_bytes", "bytes", "id", "mode"), &MultiplayerAPI::send_bytes, DEFVAL(NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST), DEFVAL(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE)); ClassDB::bind_method(D_METHOD("has_network_peer"), &MultiplayerAPI::has_network_peer); ClassDB::bind_method(D_METHOD("get_network_peer"), &MultiplayerAPI::get_network_peer); @@ -1221,6 +1226,7 @@ void MultiplayerAPI::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_object_decoding"), "set_allow_object_decoding", "is_object_decoding_allowed"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root_node", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_root_node", "get_root_node"); ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false); ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id"))); diff --git a/core/io/multiplayer_api.h b/core/io/multiplayer_api.h index 06eab7796c..7f88b53a27 100644 --- a/core/io/multiplayer_api.h +++ b/core/io/multiplayer_api.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,7 @@ #define MULTIPLAYER_API_H #include "core/io/networked_multiplayer_peer.h" -#include "core/reference.h" +#include "core/object/reference.h" class MultiplayerAPI : public Reference { GDCLASS(MultiplayerAPI, Reference); @@ -102,7 +102,6 @@ public: }; enum RPCMode { - RPC_MODE_DISABLED, // No rpc for this method, calls to this will be blocked (default) RPC_MODE_REMOTE, // Using rpc() on it will call method / set property in all remote peers RPC_MODE_MASTER, // Using rpc() on it will call method on wherever the master is, be it local or remote @@ -115,6 +114,7 @@ public: void poll(); void clear(); void set_root_node(Node *p_node); + Node *get_root_node(); void set_network_peer(const Ref<NetworkedMultiplayerPeer> &p_peer); Ref<NetworkedMultiplayerPeer> get_network_peer() const; Error send_bytes(Vector<uint8_t> p_data, int p_to = NetworkedMultiplayerPeer::TARGET_PEER_BROADCAST, NetworkedMultiplayerPeer::TransferMode p_mode = NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE); diff --git a/core/io/net_socket.cpp b/core/io/net_socket.cpp index 130a2e245e..b51d26ba83 100644 --- a/core/io/net_socket.cpp +++ b/core/io/net_socket.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/net_socket.h b/core/io/net_socket.h index 746945eced..bc09477693 100644 --- a/core/io/net_socket.h +++ b/core/io/net_socket.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,7 @@ #define NET_SOCKET_H #include "core/io/ip.h" -#include "core/reference.h" +#include "core/object/reference.h" class NetSocket : public Reference { protected: diff --git a/core/io/networked_multiplayer_peer.cpp b/core/io/networked_multiplayer_peer.cpp index f521f2bb79..b6af046e77 100644 --- a/core/io/networked_multiplayer_peer.cpp +++ b/core/io/networked_multiplayer_peer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/networked_multiplayer_peer.h b/core/io/networked_multiplayer_peer.h index dc76237f45..7c90f97d88 100644 --- a/core/io/networked_multiplayer_peer.h +++ b/core/io/networked_multiplayer_peer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/packed_data_container.cpp b/core/io/packed_data_container.cpp index e335ec0daa..a0b97772e6 100644 --- a/core/packed_data_container.cpp +++ b/core/io/packed_data_container.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -39,6 +39,9 @@ Variant PackedDataContainer::getvar(const Variant &p_key, bool *r_valid) const { if (r_valid) { *r_valid = !err; } + if (err) { + return Object::getvar(p_key, r_valid); + } return ret; } @@ -243,7 +246,7 @@ uint32_t PackedDataContainer::_pack(const Variant &p_data, Vector<uint8_t> &tmpd } break; // misc types - case Variant::_RID: + case Variant::RID: case Variant::OBJECT: { return _pack(Variant(), tmpdata, string_cache); } break; diff --git a/core/packed_data_container.h b/core/io/packed_data_container.h index 28ec9cc87c..7791e21bb3 100644 --- a/core/packed_data_container.h +++ b/core/io/packed_data_container.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef PACKED_DATA_CONTAINER_H #define PACKED_DATA_CONTAINER_H -#include "core/resource.h" +#include "core/io/resource.h" class PackedDataContainer : public Resource { GDCLASS(PackedDataContainer, Resource); @@ -84,7 +84,7 @@ class PackedDataContainerRef : public Reference { GDCLASS(PackedDataContainerRef, Reference); friend class PackedDataContainer; - uint32_t offset; + uint32_t offset = 0; Ref<PackedDataContainer> from; protected: diff --git a/core/io/packet_peer.cpp b/core/io/packet_peer.cpp index dacd548a3e..318fd10243 100644 --- a/core/io/packet_peer.cpp +++ b/core/io/packet_peer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,8 +30,8 @@ #include "packet_peer.h" +#include "core/config/project_settings.h" #include "core/io/marshalls.h" -#include "core/project_settings.h" /* helpers / binders */ @@ -151,11 +151,6 @@ void PacketPeer::_bind_methods() { /***************/ -void PacketPeerStream::_set_stream_peer(REF p_peer) { - ERR_FAIL_COND_MSG(p_peer.is_null(), "It's not a reference to a valid Resource object."); - set_stream_peer(p_peer); -} - void PacketPeerStream::_bind_methods() { ClassDB::bind_method(D_METHOD("set_stream_peer", "peer"), &PacketPeerStream::set_stream_peer); ClassDB::bind_method(D_METHOD("get_stream_peer"), &PacketPeerStream::get_stream_peer); @@ -263,10 +258,8 @@ int PacketPeerStream::get_max_packet_size() const { } void PacketPeerStream::set_stream_peer(const Ref<StreamPeer> &p_peer) { - //ERR_FAIL_COND(p_peer.is_null()); - if (p_peer.ptr() != peer.ptr()) { - ring_buffer.advance_read(ring_buffer.data_left()); // reset the ring buffer + ring_buffer.advance_read(ring_buffer.data_left()); // Reset the ring buffer. } peer = p_peer; diff --git a/core/io/packet_peer.h b/core/io/packet_peer.h index 92cdbc4151..9e03c44750 100644 --- a/core/io/packet_peer.h +++ b/core/io/packet_peer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,8 +32,8 @@ #define PACKET_PEER_H #include "core/io/stream_peer.h" -#include "core/object.h" -#include "core/ring_buffer.h" +#include "core/object/class_db.h" +#include "core/templates/ring_buffer.h" class PacketPeer : public Reference { GDCLASS(PacketPeer, Reference); @@ -86,7 +86,6 @@ class PacketPeerStream : public PacketPeer { Error _poll_buffer() const; protected: - void _set_stream_peer(REF p_peer); static void _bind_methods(); public: diff --git a/core/io/packet_peer_dtls.cpp b/core/io/packet_peer_dtls.cpp index 632f86a9f6..bac98e20e7 100644 --- a/core/io/packet_peer_dtls.cpp +++ b/core/io/packet_peer_dtls.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,8 +29,8 @@ /*************************************************************************/ #include "packet_peer_dtls.h" +#include "core/config/project_settings.h" #include "core/os/file_access.h" -#include "core/project_settings.h" PacketPeerDTLS *(*PacketPeerDTLS::_create)() = nullptr; bool PacketPeerDTLS::available = false; diff --git a/core/io/packet_peer_dtls.h b/core/io/packet_peer_dtls.h index c2ff4e1a7f..31c52f539f 100644 --- a/core/io/packet_peer_dtls.h +++ b/core/io/packet_peer_dtls.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/packet_peer_udp.cpp b/core/io/packet_peer_udp.cpp index e633a56d54..d8d63d976f 100644 --- a/core/io/packet_peer_udp.cpp +++ b/core/io/packet_peer_udp.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -178,7 +178,6 @@ Error PacketPeerUDP::listen(int p_port, const IP_Address &p_bind_address, int p_ } _sock->set_blocking_enabled(false); - _sock->set_reuse_address_enabled(true); _sock->set_broadcasting_enabled(broadcast); err = _sock->bind(p_bind_address, p_port); diff --git a/core/io/packet_peer_udp.h b/core/io/packet_peer_udp.h index 9a44a1ebea..4bac6994fc 100644 --- a/core/io/packet_peer_udp.h +++ b/core/io/packet_peer_udp.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp index 5480d3c535..a0697ca18b 100644 --- a/core/io/pck_packer.cpp +++ b/core/io/pck_packer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -53,7 +53,7 @@ void PCKPacker::_bind_methods() { } Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &p_key, bool p_encrypt_directory) { - ERR_FAIL_COND_V_MSG((p_key.empty() || !p_key.is_valid_hex_number(false) || p_key.length() != 64), ERR_CANT_CREATE, "Invalid Encryption Key (must be 64 characters long)."); + ERR_FAIL_COND_V_MSG((p_key.is_empty() || !p_key.is_valid_hex_number(false) || p_key.length() != 64), ERR_CANT_CREATE, "Invalid Encryption Key (must be 64 characters long)."); String _key = p_key.to_lower(); key.resize(32); diff --git a/core/io/pck_packer.h b/core/io/pck_packer.h index a6054dff2c..dec8f8748d 100644 --- a/core/io/pck_packer.h +++ b/core/io/pck_packer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef PCK_PACKER_H #define PCK_PACKER_H -#include "core/reference.h" +#include "core/object/reference.h" class FileAccess; @@ -39,7 +39,7 @@ class PCKPacker : public Reference { GDCLASS(PCKPacker, Reference); FileAccess *file = nullptr; - int alignment; + int alignment = 0; uint64_t ofs = 0; Vector<uint8_t> key; @@ -50,9 +50,9 @@ class PCKPacker : public Reference { struct File { String path; String src_path; - uint64_t ofs; - uint64_t size; - bool encrypted; + uint64_t ofs = 0; + uint64_t size = 0; + bool encrypted = false; Vector<uint8_t> md5; }; Vector<File> files; diff --git a/core/resource.cpp b/core/io/resource.cpp index 3b589793ef..716da5e395 100644 --- a/core/resource.cpp +++ b/core/io/resource.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,9 +32,9 @@ #include "core/core_string_names.h" #include "core/io/resource_loader.h" +#include "core/object/script_language.h" #include "core/os/file_access.h" #include "core/os/os.h" -#include "core/script_language.h" #include "scene/main/node.h" //only so casting works #include <stdio.h> @@ -147,8 +147,8 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Res List<PropertyInfo> plist; get_property_list(&plist); - Resource *r = Object::cast_to<Resource>(ClassDB::instance(get_class())); - ERR_FAIL_COND_V(!r, Ref<Resource>()); + Ref<Resource> r = Object::cast_to<Resource>(ClassDB::instance(get_class())); + ERR_FAIL_COND_V(r.is_null(), Ref<Resource>()); r->local_scene = p_for_scene; @@ -175,9 +175,7 @@ Ref<Resource> Resource::duplicate_for_local_scene(Node *p_for_scene, Map<Ref<Res r->set(E->get().name, p); } - RES res = Ref<Resource>(r); - - return res; + return r; } void Resource::configure_for_local_scene(Node *p_for_scene, Map<Ref<Resource>, Ref<Resource>> &remap_cache) { @@ -209,8 +207,8 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const { List<PropertyInfo> plist; get_property_list(&plist); - Resource *r = (Resource *)ClassDB::instance(get_class()); - ERR_FAIL_COND_V(!r, Ref<Resource>()); + Ref<Resource> r = (Resource *)ClassDB::instance(get_class()); + ERR_FAIL_COND_V(r.is_null(), Ref<Resource>()); for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) { @@ -230,7 +228,7 @@ Ref<Resource> Resource::duplicate(bool p_subresources) const { } } - return Ref<Resource>(r); + return r; } void Resource::_set_path(const String &p_path) { diff --git a/core/resource.h b/core/io/resource.h index 7699d48735..eda18a8538 100644 --- a/core/resource.h +++ b/core/io/resource.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,11 +31,10 @@ #ifndef RESOURCE_H #define RESOURCE_H -#include "core/class_db.h" -#include "core/object.h" -#include "core/reference.h" -#include "core/safe_refcount.h" -#include "core/self_list.h" +#include "core/object/class_db.h" +#include "core/object/reference.h" +#include "core/templates/safe_refcount.h" +#include "core/templates/self_list.h" #define RES_BASE_EXTENSION(m_ext) \ public: \ diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp index 21de7835ce..ae4643a19f 100644 --- a/core/io/resource_format_binary.cpp +++ b/core/io/resource_format_binary.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,18 +30,17 @@ #include "resource_format_binary.h" -#include "core/image.h" +#include "core/config/project_settings.h" #include "core/io/file_access_compressed.h" +#include "core/io/image.h" #include "core/io/marshalls.h" #include "core/os/dir_access.h" -#include "core/project_settings.h" #include "core/version.h" //#define print_bl(m_what) print_line(m_what) #define print_bl(m_what) (void)(m_what) enum { - //numbering must be different from variant, in case new variant types are added (variant must be always contiguous for jumptable optimization) VARIANT_NIL = 1, VARIANT_BOOL = 2, @@ -90,7 +89,6 @@ enum { FORMAT_VERSION = 3, FORMAT_VERSION_CAN_RENAME_DEPS = 1, FORMAT_VERSION_NO_NODEPATH_PROPERTY = 3, - }; void ResourceLoaderBinary::_advance_padding(uint32_t p_len) { @@ -1467,7 +1465,7 @@ void ResourceFormatSaverBinaryInstance::write_variant(FileAccess *f, const Varia } } break; - case Variant::_RID: { + case Variant::RID: { f->store_32(VARIANT_RID); WARN_PRINT("Can't save RIDs."); RID val = p_property; diff --git a/core/io/resource_format_binary.h b/core/io/resource_format_binary.h index 54cddca49e..428725f1d2 100644 --- a/core/io/resource_format_binary.h +++ b/core/io/resource_format_binary.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/resource_importer.cpp b/core/io/resource_importer.cpp index 4d980bcf1a..d86877ee14 100644 --- a/core/io/resource_importer.cpp +++ b/core/io/resource_importer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,9 @@ #include "resource_importer.h" +#include "core/config/project_settings.h" #include "core/os/os.h" -#include "core/project_settings.h" -#include "core/variant_parser.h" +#include "core/variant/variant_parser.h" bool ResourceFormatImporter::SortImporterByName::operator()(const Ref<ResourceImporter> &p_a, const Ref<ResourceImporter> &p_b) const { return p_a->get_importer_name() < p_b->get_importer_name(); @@ -192,10 +192,6 @@ bool ResourceFormatImporter::recognize_path(const String &p_path, const String & return FileAccess::exists(p_path + ".import"); } -bool ResourceFormatImporter::can_be_imported(const String &p_path) const { - return ResourceFormatLoader::recognize_path(p_path); -} - int ResourceFormatImporter::get_import_order(const String &p_path) const { Ref<ResourceImporter> importer; diff --git a/core/io/resource_importer.h b/core/io/resource_importer.h index d31a9a0194..d31273e3cb 100644 --- a/core/io/resource_importer.h +++ b/core/io/resource_importer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -70,7 +70,6 @@ public: virtual String get_import_group_file(const String &p_path) const; virtual bool exists(const String &p_path) const; - virtual bool can_be_imported(const String &p_path) const; virtual int get_import_order(const String &p_path) const; String get_internal_resource_path(const String &p_path) const; @@ -102,6 +101,7 @@ public: virtual String get_resource_type() const = 0; virtual float get_priority() const { return 1.0; } virtual int get_import_order() const { return 0; } + virtual int get_format_version() const { return 0; } struct ImportOption { PropertyInfo option; diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index b5c598e860..821e468aee 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,13 +30,13 @@ #include "resource_loader.h" +#include "core/config/project_settings.h" #include "core/io/resource_importer.h" #include "core/os/file_access.h" #include "core/os/os.h" -#include "core/print_string.h" -#include "core/project_settings.h" -#include "core/translation.h" -#include "core/variant_parser.h" +#include "core/string/print_string.h" +#include "core/string/translation.h" +#include "core/variant/variant_parser.h" #ifdef DEBUG_LOAD_THREADED #define print_lt(m_text) print_line(m_text) @@ -1057,7 +1057,7 @@ bool ResourceLoader::add_custom_resource_format_loader(String script_path) { ERR_FAIL_COND_V_MSG(obj == nullptr, false, "Cannot instance script as custom resource loader, expected 'ResourceFormatLoader' inheritance, got: " + String(ibt) + "."); - ResourceFormatLoader *crl = Object::cast_to<ResourceFormatLoader>(obj); + Ref<ResourceFormatLoader> crl = Object::cast_to<ResourceFormatLoader>(obj); crl->set_script(s); ResourceLoader::add_resource_format_loader(crl); diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h index 9322b5273a..dbf6be46c5 100644 --- a/core/io/resource_loader.h +++ b/core/io/resource_loader.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +31,9 @@ #ifndef RESOURCE_LOADER_H #define RESOURCE_LOADER_H +#include "core/io/resource.h" #include "core/os/semaphore.h" #include "core/os/thread.h" -#include "core/resource.h" class ResourceFormatLoader : public Reference { GDCLASS(ResourceFormatLoader, Reference); diff --git a/core/io/resource_saver.cpp b/core/io/resource_saver.cpp index a8da215b61..7ebc7f34b3 100644 --- a/core/io/resource_saver.cpp +++ b/core/io/resource_saver.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,10 +29,10 @@ /*************************************************************************/ #include "resource_saver.h" +#include "core/config/project_settings.h" #include "core/io/resource_loader.h" +#include "core/object/script_language.h" #include "core/os/file_access.h" -#include "core/project_settings.h" -#include "core/script_language.h" Ref<ResourceFormatSaver> ResourceSaver::saver[MAX_SAVERS]; @@ -214,7 +214,7 @@ bool ResourceSaver::add_custom_resource_format_saver(String script_path) { ERR_FAIL_COND_V_MSG(obj == nullptr, false, "Cannot instance script as custom resource saver, expected 'ResourceFormatSaver' inheritance, got: " + String(ibt) + "."); - ResourceFormatSaver *crl = Object::cast_to<ResourceFormatSaver>(obj); + Ref<ResourceFormatSaver> crl = Object::cast_to<ResourceFormatSaver>(obj); crl->set_script(s); ResourceSaver::add_resource_format_saver(crl); diff --git a/core/io/resource_saver.h b/core/io/resource_saver.h index 8b4cdd86f8..2c9e8f1aa3 100644 --- a/core/io/resource_saver.h +++ b/core/io/resource_saver.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef RESOURCE_SAVER_H #define RESOURCE_SAVER_H -#include "core/resource.h" +#include "core/io/resource.h" class ResourceFormatSaver : public Reference { GDCLASS(ResourceFormatSaver, Reference); @@ -63,7 +63,6 @@ class ResourceSaver { public: enum SaverFlags { - FLAG_RELATIVE_PATHS = 1, FLAG_BUNDLE_RESOURCES = 2, FLAG_CHANGE_PATH = 4, diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp index 403f61bb24..8407d55196 100644 --- a/core/io/stream_peer.cpp +++ b/core/io/stream_peer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h index 39097a57f2..dadedbd2dc 100644 --- a/core/io/stream_peer.h +++ b/core/io/stream_peer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef STREAM_PEER_H #define STREAM_PEER_H -#include "core/reference.h" +#include "core/object/reference.h" class StreamPeer : public Reference { GDCLASS(StreamPeer, Reference); diff --git a/core/io/stream_peer_ssl.cpp b/core/io/stream_peer_ssl.cpp index 3dc31c6769..6f5a06474c 100644 --- a/core/io/stream_peer_ssl.cpp +++ b/core/io/stream_peer_ssl.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "stream_peer_ssl.h" -#include "core/engine.h" +#include "core/config/engine.h" StreamPeerSSL *(*StreamPeerSSL::_create)() = nullptr; diff --git a/core/io/stream_peer_ssl.h b/core/io/stream_peer_ssl.h index 81b95b856d..1df9ced08c 100644 --- a/core/io/stream_peer_ssl.h +++ b/core/io/stream_peer_ssl.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index cce728c30a..760710a9eb 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "stream_peer_tcp.h" -#include "core/project_settings.h" +#include "core/config/project_settings.h" Error StreamPeerTCP::_poll_connection() { ERR_FAIL_COND_V(status != STATUS_CONNECTING || !_sock.is_valid() || !_sock->is_open(), FAILED); diff --git a/core/io/stream_peer_tcp.h b/core/io/stream_peer_tcp.h index 45205866b4..10b90908d4 100644 --- a/core/io/stream_peer_tcp.h +++ b/core/io/stream_peer_tcp.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -42,7 +42,6 @@ class StreamPeerTCP : public StreamPeer { public: enum Status { - STATUS_NONE, STATUS_CONNECTING, STATUS_CONNECTED, diff --git a/core/io/tcp_server.cpp b/core/io/tcp_server.cpp index d7061b6bf4..323d2bbd7f 100644 --- a/core/io/tcp_server.cpp +++ b/core/io/tcp_server.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/tcp_server.h b/core/io/tcp_server.h index eb715a745c..f06ddd2d99 100644 --- a/core/io/tcp_server.h +++ b/core/io/tcp_server.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/translation_loader_po.cpp b/core/io/translation_loader_po.cpp index d8ddb213c3..ce2c3eb1cd 100644 --- a/core/io/translation_loader_po.cpp +++ b/core/io/translation_loader_po.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #include "translation_loader_po.h" #include "core/os/file_access.h" -#include "core/translation.h" -#include "core/translation_po.h" +#include "core/string/translation.h" +#include "core/string/translation_po.h" RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) { enum Status { @@ -70,7 +70,7 @@ RES TranslationLoaderPO::load_translation(FileAccess *f, Error *r_error) { is_eof = f->eof_reached(); // If we reached last line and it's not a content line, break, otherwise let processing that last loop - if (is_eof && l.empty()) { + if (is_eof && l.is_empty()) { if (status == STATUS_READING_ID || status == STATUS_READING_CONTEXT || (status == STATUS_READING_PLURAL && plural_index != plural_forms - 1)) { memdelete(f); ERR_FAIL_V_MSG(RES(), "Unexpected EOF while reading PO file at: " + path + ":" + itos(line)); diff --git a/core/io/translation_loader_po.h b/core/io/translation_loader_po.h index a196a37dc0..a524972588 100644 --- a/core/io/translation_loader_po.h +++ b/core/io/translation_loader_po.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +33,7 @@ #include "core/io/resource_loader.h" #include "core/os/file_access.h" -#include "core/translation.h" +#include "core/string/translation.h" class TranslationLoaderPO : public ResourceFormatLoader { public: diff --git a/core/io/udp_server.cpp b/core/io/udp_server.cpp index acd15aadc6..f56fb431ef 100644 --- a/core/io/udp_server.cpp +++ b/core/io/udp_server.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/udp_server.h b/core/io/udp_server.h index 3175b09b19..bbd2f951c9 100644 --- a/core/io/udp_server.h +++ b/core/io/udp_server.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp index fc75ac7d1e..905be6089d 100644 --- a/core/io/xml_parser.cpp +++ b/core/io/xml_parser.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "xml_parser.h" -#include "core/print_string.h" +#include "core/string/print_string.h" //#define DEBUG_XML diff --git a/core/io/xml_parser.h b/core/io/xml_parser.h index ee2174d52c..01af6a90ad 100644 --- a/core/io/xml_parser.h +++ b/core/io/xml_parser.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,10 +31,10 @@ #ifndef XML_PARSER_H #define XML_PARSER_H +#include "core/object/reference.h" #include "core/os/file_access.h" -#include "core/reference.h" -#include "core/ustring.h" -#include "core/vector.h" +#include "core/string/ustring.h" +#include "core/templates/vector.h" /* Based on irrXML (see their zlib license). Added mainly for compatibility with their Collada loader. diff --git a/core/io/zip_io.cpp b/core/io/zip_io.cpp index b8e7fd34d0..4b4a46e198 100644 --- a/core/io/zip_io.cpp +++ b/core/io/zip_io.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/io/zip_io.h b/core/io/zip_io.h index ba2065b5d1..52691c65e9 100644 --- a/core/io/zip_io.h +++ b/core/io/zip_io.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/make_binders.py b/core/make_binders.py deleted file mode 100644 index 7d0d08cde6..0000000000 --- a/core/make_binders.py +++ /dev/null @@ -1,390 +0,0 @@ -# -*- coding: ibm850 -*- - -template_typed = """ -#ifdef TYPED_METHOD_BIND -template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$> -class MethodBind$argc$$ifret R$$ifconst C$ : public MethodBind { -public: - - $ifret R$ $ifnoret void$ (T::*method)($arg, P@$) $ifconst const$; -#ifdef DEBUG_METHODS_ENABLED - virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); } - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { - $ifret if (p_arg==-1) return GetTypeInfo<R>::METADATA;$ - $arg if (p_arg==(@-1)) return GetTypeInfo<P@>::METADATA; - $ - return GodotTypeInfo::METADATA_NONE; - } - Variant::Type _get_argument_type(int p_argument) const { - $ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo<R>::VARIANT_TYPE;$ - $arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo<P@>::VARIANT_TYPE; - $ - return Variant::NIL; - } - virtual PropertyInfo _gen_argument_type_info(int p_argument) const { - $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_info();$ - $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_info(); - $ - return PropertyInfo(); - } -#endif - virtual String get_instance_class() const { - return T::get_class_static(); - } - - virtual Variant call(Object* p_object,const Variant** p_args,int p_arg_count, Callable::CallError& r_error) { - - T *instance=Object::cast_to<T>(p_object); - r_error.error=Callable::CallError::CALL_OK; -#ifdef DEBUG_METHODS_ENABLED - - ERR_FAIL_COND_V(!instance,Variant()); - if (p_arg_count>get_argument_count()) { - r_error.error=Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument=get_argument_count(); - return Variant(); - - } - if (p_arg_count<(get_argument_count()-get_default_argument_count())) { - - r_error.error=Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument=get_argument_count()-get_default_argument_count(); - return Variant(); - } - $arg CHECK_ARG(@); - $ -#endif - $ifret Variant ret = $(instance->*method)($arg, _VC(@)$); - $ifret return Variant(ret);$ - $ifnoret return Variant();$ - } - -#ifdef PTRCALL_ENABLED - virtual void ptrcall(Object*p_object,const void** p_args,void *r_ret) { - - T *instance=Object::cast_to<T>(p_object); - $ifret PtrToArg<R>::encode( $ (instance->*method)($arg, PtrToArg<P@>::convert(p_args[@-1])$) $ifret ,r_ret)$ ; - } -#endif - MethodBind$argc$$ifret R$$ifconst C$ () { -#ifdef DEBUG_METHODS_ENABLED - _set_const($ifconst true$$ifnoconst false$); - _generate_argument_types($argc$); -#else - set_argument_count($argc$); -#endif - - $ifret _set_returns(true); $ - } -}; - -template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$> -MethodBind* create_method_bind($ifret R$ $ifnoret void$ (T::*p_method)($arg, P@$) $ifconst const$ ) { - - MethodBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$> * a = memnew( (MethodBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$>) ); - a->method=p_method; - return a; -} -#endif -""" - -template = """ -#ifndef TYPED_METHOD_BIND -$iftempl template<$ $ifret class R$ $ifretargs ,$ $arg, class P@$ $iftempl >$ -class MethodBind$argc$$ifret R$$ifconst C$ : public MethodBind { - -public: - - StringName type_name; - $ifret R$ $ifnoret void$ (__UnexistingClass::*method)($arg, P@$) $ifconst const$; - -#ifdef DEBUG_METHODS_ENABLED - virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); } - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { - $ifret if (p_arg==-1) return GetTypeInfo<R>::METADATA;$ - $arg if (p_arg==(@-1)) return GetTypeInfo<P@>::METADATA; - $ - return GodotTypeInfo::METADATA_NONE; - } - - Variant::Type _get_argument_type(int p_argument) const { - $ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo<R>::VARIANT_TYPE;$ - $arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo<P@>::VARIANT_TYPE; - $ - return Variant::NIL; - } - - virtual PropertyInfo _gen_argument_type_info(int p_argument) const { - $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_info();$ - $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_info(); - $ - return PropertyInfo(); - } - -#endif - virtual String get_instance_class() const { - return type_name; - } - - virtual Variant call(Object* p_object,const Variant** p_args,int p_arg_count, Callable::CallError& r_error) { - - __UnexistingClass *instance = (__UnexistingClass*)p_object; - - r_error.error=Callable::CallError::CALL_OK; -#ifdef DEBUG_METHODS_ENABLED - - ERR_FAIL_COND_V(!instance,Variant()); - if (p_arg_count>get_argument_count()) { - r_error.error=Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument=get_argument_count(); - return Variant(); - } - - if (p_arg_count<(get_argument_count()-get_default_argument_count())) { - - r_error.error=Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument=get_argument_count()-get_default_argument_count(); - return Variant(); - } - - $arg CHECK_ARG(@); - $ -#endif - $ifret Variant ret = $(instance->*method)($arg, _VC(@)$); - $ifret return Variant(ret);$ - $ifnoret return Variant();$ - } -#ifdef PTRCALL_ENABLED - virtual void ptrcall(Object*p_object,const void** p_args,void *r_ret) { - __UnexistingClass *instance = (__UnexistingClass*)p_object; - $ifret PtrToArg<R>::encode( $ (instance->*method)($arg, PtrToArg<P@>::convert(p_args[@-1])$) $ifret ,r_ret) $ ; - } -#endif - MethodBind$argc$$ifret R$$ifconst C$ () { -#ifdef DEBUG_METHODS_ENABLED - _set_const($ifconst true$$ifnoconst false$); - _generate_argument_types($argc$); -#else - set_argument_count($argc$); -#endif - $ifret _set_returns(true); $ - - - } -}; - -template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$> -MethodBind* create_method_bind($ifret R$ $ifnoret void$ (T::*p_method)($arg, P@$) $ifconst const$ ) { - - MethodBind$argc$$ifret R$$ifconst C$ $iftempl <$ $ifret R$ $ifretargs ,$ $arg, P@$ $iftempl >$ * a = memnew( (MethodBind$argc$$ifret R$$ifconst C$ $iftempl <$ $ifret R$ $ifretargs ,$ $arg, P@$ $iftempl >$) ); - union { - - $ifret R$ $ifnoret void$ (T::*sm)($arg, P@$) $ifconst const$; - $ifret R$ $ifnoret void$ (__UnexistingClass::*dm)($arg, P@$) $ifconst const$; - } u; - u.sm=p_method; - a->method=u.dm; - a->type_name=T::get_class_static(); - return a; -} -#endif -""" - - -template_typed_free_func = """ -#ifdef TYPED_METHOD_BIND -template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$> -class FunctionBind$argc$$ifret R$$ifconst C$ : public MethodBind { -public: - - $ifret R$ $ifnoret void$ (*method) ($ifconst const$ T *$ifargs , $$arg, P@$); -#ifdef DEBUG_METHODS_ENABLED - virtual Variant::Type _gen_argument_type(int p_arg) const { return _get_argument_type(p_arg); } - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { - $ifret if (p_arg==-1) return GetTypeInfo<R>::METADATA;$ - $arg if (p_arg==(@-1)) return GetTypeInfo<P@>::METADATA; - $ - return GodotTypeInfo::METADATA_NONE; - } - Variant::Type _get_argument_type(int p_argument) const { - $ifret if (p_argument==-1) return (Variant::Type)GetTypeInfo<R>::VARIANT_TYPE;$ - $arg if (p_argument==(@-1)) return (Variant::Type)GetTypeInfo<P@>::VARIANT_TYPE; - $ - return Variant::NIL; - } - virtual PropertyInfo _gen_argument_type_info(int p_argument) const { - $ifret if (p_argument==-1) return GetTypeInfo<R>::get_class_info();$ - $arg if (p_argument==(@-1)) return GetTypeInfo<P@>::get_class_info(); - $ - return PropertyInfo(); - } -#endif - virtual String get_instance_class() const { - return T::get_class_static(); - } - - virtual Variant call(Object* p_object,const Variant** p_args,int p_arg_count, Callable::CallError& r_error) { - - T *instance=Object::cast_to<T>(p_object); - r_error.error=Callable::CallError::CALL_OK; -#ifdef DEBUG_METHODS_ENABLED - - ERR_FAIL_COND_V(!instance,Variant()); - if (p_arg_count>get_argument_count()) { - r_error.error=Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument=get_argument_count(); - return Variant(); - - } - if (p_arg_count<(get_argument_count()-get_default_argument_count())) { - - r_error.error=Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument=get_argument_count()-get_default_argument_count(); - return Variant(); - } - $arg CHECK_ARG(@); - $ -#endif - $ifret Variant ret = $(method)(instance$ifargs , $$arg, _VC(@)$); - $ifret return Variant(ret);$ - $ifnoret return Variant();$ - } - -#ifdef PTRCALL_ENABLED - virtual void ptrcall(Object*p_object,const void** p_args,void *r_ret) { - - T *instance=Object::cast_to<T>(p_object); - $ifret PtrToArg<R>::encode( $ (method)(instance$ifargs , $$arg, PtrToArg<P@>::convert(p_args[@-1])$) $ifret ,r_ret)$ ; - } -#endif - FunctionBind$argc$$ifret R$$ifconst C$ () { -#ifdef DEBUG_METHODS_ENABLED - _set_const($ifconst true$$ifnoconst false$); - _generate_argument_types($argc$); -#else - set_argument_count($argc$); -#endif - - $ifret _set_returns(true); $ - } -}; - -template<class T $ifret ,class R$ $ifargs ,$ $arg, class P@$> -MethodBind* create_method_bind($ifret R$ $ifnoret void$ (*p_method)($ifconst const$ T *$ifargs , $$arg, P@$) ) { - - FunctionBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$> * a = memnew( (FunctionBind$argc$$ifret R$$ifconst C$<T $ifret ,R$ $ifargs ,$ $arg, P@$>) ); - a->method=p_method; - return a; -} -#endif -""" - - -def make_version(template, nargs, argmax, const, ret): - - intext = template - from_pos = 0 - outtext = "" - - while True: - to_pos = intext.find("$", from_pos) - if to_pos == -1: - outtext += intext[from_pos:] - break - else: - outtext += intext[from_pos:to_pos] - end = intext.find("$", to_pos + 1) - if end == -1: - break # ignore - macro = intext[to_pos + 1 : end] - cmd = "" - data = "" - - if macro.find(" ") != -1: - cmd = macro[0 : macro.find(" ")] - data = macro[macro.find(" ") + 1 :] - else: - cmd = macro - - if cmd == "argc": - outtext += str(nargs) - if cmd == "ifret" and ret: - outtext += data - if cmd == "ifargs" and nargs: - outtext += data - if cmd == "ifretargs" and nargs and ret: - outtext += data - if cmd == "ifconst" and const: - outtext += data - elif cmd == "ifnoconst" and not const: - outtext += data - elif cmd == "ifnoret" and not ret: - outtext += data - elif cmd == "iftempl" and (nargs > 0 or ret): - outtext += data - elif cmd == "arg,": - for i in range(1, nargs + 1): - if i > 1: - outtext += ", " - outtext += data.replace("@", str(i)) - elif cmd == "arg": - for i in range(1, nargs + 1): - outtext += data.replace("@", str(i)) - elif cmd == "noarg": - for i in range(nargs + 1, argmax + 1): - outtext += data.replace("@", str(i)) - - from_pos = end + 1 - - return outtext - - -def run(target, source, env): - - versions = 15 - versions_ext = 6 - text = "" - text_ext = "" - text_free_func = "#ifndef METHOD_BIND_FREE_FUNC_H\n#define METHOD_BIND_FREE_FUNC_H\n" - text_free_func += "\n//including this header file allows method binding to use free functions\n" - text_free_func += ( - "//note that the free function must have a pointer to an instance of the class as its first parameter\n" - ) - - for i in range(0, versions + 1): - - t = "" - t += make_version(template, i, versions, False, False) - t += make_version(template_typed, i, versions, False, False) - t += make_version(template, i, versions, False, True) - t += make_version(template_typed, i, versions, False, True) - t += make_version(template, i, versions, True, False) - t += make_version(template_typed, i, versions, True, False) - t += make_version(template, i, versions, True, True) - t += make_version(template_typed, i, versions, True, True) - if i >= versions_ext: - text_ext += t - else: - text += t - - text_free_func += make_version(template_typed_free_func, i, versions, False, False) - text_free_func += make_version(template_typed_free_func, i, versions, False, True) - text_free_func += make_version(template_typed_free_func, i, versions, True, False) - text_free_func += make_version(template_typed_free_func, i, versions, True, True) - - text_free_func += "#endif" - - with open(target[0], "w") as f: - f.write(text) - - with open(target[1], "w") as f: - f.write(text_ext) - - with open(target[2], "w") as f: - f.write(text_free_func) - - -if __name__ == "__main__": - from platform_methods import subprocess_main - - subprocess_main(globals()) diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index 30f712b2c3..88e11a630c 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,11 +31,11 @@ #include "a_star.h" #include "core/math/geometry_3d.h" -#include "core/script_language.h" +#include "core/object/script_language.h" #include "scene/scene_string_names.h" int AStar::get_available_point_id() const { - if (points.empty()) { + if (points.is_empty()) { return 1; } @@ -341,7 +341,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { begin_point->f_score = _estimate_cost(begin_point->id, end_point->id); open_list.push_back(begin_point); - while (!open_list.empty()) { + while (!open_list.is_empty()) { Point *p = open_list[0]; // The currently processed point if (p == end_point) { @@ -805,7 +805,7 @@ bool AStar2D::_solve(AStar::Point *begin_point, AStar::Point *end_point) { begin_point->f_score = _estimate_cost(begin_point->id, end_point->id); open_list.push_back(begin_point); - while (!open_list.empty()) { + while (!open_list.is_empty()) { AStar::Point *p = open_list[0]; // The currently processed point if (p == end_point) { diff --git a/core/math/a_star.h b/core/math/a_star.h index ba1c3033b8..4c61abd91c 100644 --- a/core/math/a_star.h +++ b/core/math/a_star.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef A_STAR_H #define A_STAR_H -#include "core/oa_hash_map.h" -#include "core/reference.h" +#include "core/object/reference.h" +#include "core/templates/oa_hash_map.h" /** A* pathfinding algorithm @@ -47,20 +47,20 @@ class AStar : public Reference { struct Point { Point() {} - int id; + int id = 0; Vector3 pos; - real_t weight_scale; - bool enabled; + real_t weight_scale = 0; + bool enabled = false; OAHashMap<int, Point *> neighbours = 4u; OAHashMap<int, Point *> unlinked_neighbours = 4u; // Used for pathfinding. - Point *prev_point; - real_t g_score; - real_t f_score; - uint64_t open_pass; - uint64_t closed_pass; + Point *prev_point = nullptr; + real_t g_score = 0; + real_t f_score = 0; + uint64_t open_pass = 0; + uint64_t closed_pass = 0; }; struct SortPoints { diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp index f5c667dab0..2c721997d8 100644 --- a/core/math/aabb.cpp +++ b/core/math/aabb.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,8 @@ #include "aabb.h" -#include "core/print_string.h" +#include "core/string/print_string.h" +#include "core/variant/variant.h" real_t AABB::get_area() const { return size.x * size.y * size.z; @@ -375,6 +376,21 @@ void AABB::get_edge(int p_edge, Vector3 &r_from, Vector3 &r_to) const { } } +Variant AABB::intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const { + Vector3 inters; + if (intersects_segment(p_from, p_to, &inters)) { + return inters; + } + return Variant(); +} +Variant AABB::intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const { + Vector3 inters; + if (intersects_ray(p_from, p_dir, &inters)) { + return inters; + } + return Variant(); +} + AABB::operator String() const { return String() + position + " - " + size; } diff --git a/core/math/aabb.h b/core/math/aabb.h index bd1f3a1a36..2861358e32 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -39,6 +39,7 @@ * AABB / AABB (Axis Aligned Bounding Box) * This is implemented by a point (position) and the box size */ +class Variant; class AABB { public: @@ -103,6 +104,20 @@ public: return AABB(Vector3(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0), position.z + MIN(size.z, 0)), size.abs()); } + Variant intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to) const; + Variant intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const; + + _FORCE_INLINE_ void quantize(float p_unit); + _FORCE_INLINE_ AABB quantized(float p_unit) const; + + _FORCE_INLINE_ void set_end(const Vector3 &p_end) { + size = p_end - position; + } + + _FORCE_INLINE_ Vector3 get_end() const { + return position + size; + } + operator String() const; _FORCE_INLINE_ AABB() {} @@ -178,9 +193,9 @@ Vector3 AABB::get_support(const Vector3 &p_normal) const { Vector3 ofs = position + half_extents; return Vector3( - (p_normal.x > 0) ? -half_extents.x : half_extents.x, - (p_normal.y > 0) ? -half_extents.y : half_extents.y, - (p_normal.z > 0) ? -half_extents.z : half_extents.z) + + (p_normal.x > 0) ? half_extents.x : -half_extents.x, + (p_normal.y > 0) ? half_extents.y : -half_extents.y, + (p_normal.z > 0) ? half_extents.z : -half_extents.z) + ofs; } @@ -415,4 +430,28 @@ void AABB::grow_by(real_t p_amount) { size.z += 2.0 * p_amount; } +void AABB::quantize(float p_unit) { + size += position; + + position.x -= Math::fposmodp(position.x, p_unit); + position.y -= Math::fposmodp(position.y, p_unit); + position.z -= Math::fposmodp(position.z, p_unit); + + size.x -= Math::fposmodp(size.x, p_unit); + size.y -= Math::fposmodp(size.y, p_unit); + size.z -= Math::fposmodp(size.z, p_unit); + + size.x += p_unit; + size.y += p_unit; + size.z += p_unit; + + size -= position; +} + +AABB AABB::quantized(float p_unit) const { + AABB ret = *this; + ret.quantize(p_unit); + return ret; +} + #endif // AABB_H diff --git a/core/math/audio_frame.h b/core/math/audio_frame.h index 43d4a63cd3..5773da9211 100644 --- a/core/math/audio_frame.h +++ b/core/math/audio_frame.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/basis.cpp b/core/math/basis.cpp index a712ae7e3e..26b4caba39 100644 --- a/core/math/basis.cpp +++ b/core/math/basis.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,7 @@ #include "core/math/math_funcs.h" #include "core/os/copymem.h" -#include "core/print_string.h" +#include "core/string/print_string.h" #define cofac(row1, col1, row2, col2) \ (elements[row1][col1] * elements[row2][col2] - elements[row1][col2] * elements[row2][col1]) @@ -1017,15 +1017,15 @@ void Basis::set_diagonal(const Vector3 &p_diag) { elements[2][2] = p_diag.z; } -Basis Basis::slerp(const Basis &target, const real_t &t) const { +Basis Basis::slerp(const Basis &p_to, const real_t &p_weight) const { //consider scale Quat from(*this); - Quat to(target); + Quat to(p_to); - Basis b(from.slerp(to, t)); - b.elements[0] *= Math::lerp(elements[0].length(), target.elements[0].length(), t); - b.elements[1] *= Math::lerp(elements[1].length(), target.elements[1].length(), t); - b.elements[2] *= Math::lerp(elements[2].length(), target.elements[2].length(), t); + Basis b(from.slerp(to, p_weight)); + b.elements[0] *= Math::lerp(elements[0].length(), p_to.elements[0].length(), p_weight); + b.elements[1] *= Math::lerp(elements[1].length(), p_to.elements[1].length(), p_weight); + b.elements[2] *= Math::lerp(elements[2].length(), p_to.elements[2].length(), p_weight); return b; } diff --git a/core/math/basis.h b/core/math/basis.h index 2584f1ff48..56f6227313 100644 --- a/core/math/basis.h +++ b/core/math/basis.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -170,7 +170,7 @@ public: bool is_diagonal() const; bool is_rotation() const; - Basis slerp(const Basis &target, const real_t &t) const; + Basis slerp(const Basis &p_to, const real_t &p_weight) const; void rotate_sh(real_t *p_values); operator String() const; diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index c154d57a13..9ec71af57f 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #include "camera_matrix.h" #include "core/math/math_funcs.h" -#include "core/print_string.h" +#include "core/string/print_string.h" float CameraMatrix::determinant() const { return matrix[0][3] * matrix[1][2] * matrix[2][1] * matrix[3][0] - matrix[0][2] * matrix[1][3] * matrix[2][1] * matrix[3][0] - @@ -655,6 +655,17 @@ real_t CameraMatrix::get_fov() const { } } +float CameraMatrix::get_lod_multiplier() const { + if (is_orthogonal()) { + return get_viewport_half_extents().x; + } else { + float zn = get_z_near(); + float width = get_viewport_half_extents().x * 2.0; + return 1.0 / (zn / width); + } + + //usage is lod_size / (lod_distance * multiplier) < threshold +} void CameraMatrix::make_scale(const Vector3 &p_scale) { set_identity(); matrix[0][0] = p_scale.x; diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index c5cdd98377..03068bc7ea 100644 --- a/core/math/camera_matrix.h +++ b/core/math/camera_matrix.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -108,6 +108,8 @@ struct CameraMatrix { return !(*this == p_cam); } + float get_lod_multiplier() const; + CameraMatrix(); CameraMatrix(const Transform &p_transform); ~CameraMatrix(); diff --git a/core/color.cpp b/core/math/color.cpp index c61ee0e64a..4d58c8c84a 100644 --- a/core/color.cpp +++ b/core/math/color.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,10 +30,10 @@ #include "color.h" -#include "core/color_names.inc" -#include "core/map.h" +#include "color_names.inc" #include "core/math/math_funcs.h" -#include "core/print_string.h" +#include "core/string/print_string.h" +#include "core/templates/map.h" uint32_t Color::to_argb32() const { uint32_t c = (uint8_t)Math::round(a * 255); @@ -159,7 +159,7 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) { a = p_alpha; if (p_s == 0) { - // acp_hromatic (grey) + // Achromatic (grey) r = g = b = p_v; return; } @@ -217,12 +217,6 @@ void Color::invert() { b = 1.0 - b; } -void Color::contrast() { - r = Math::fmod(r + 0.5, 1.0); - g = Math::fmod(g + 0.5, 1.0); - b = Math::fmod(b + 0.5, 1.0); -} - Color Color::hex(uint32_t p_hex) { float a = (p_hex & 0xFF) / 255.0; p_hex >>= 8; @@ -284,12 +278,6 @@ Color Color::inverted() const { return c; } -Color Color::contrasted() const { - Color c = *this; - c.contrast(); - return c; -} - Color Color::html(const String &p_rgba) { String color = p_rgba; if (color.length() == 0) { @@ -367,9 +355,6 @@ bool Color::html_is_valid(const String &p_color) { } Color Color::named(const String &p_name) { - if (_named_colors.empty()) { - _populate_named_colors(); // from color_names.inc - } String name = p_name; // Normalize name name = name.replace(" ", ""); @@ -379,9 +364,31 @@ Color Color::named(const String &p_name) { name = name.replace(".", ""); name = name.to_lower(); - const Map<String, Color>::Element *color = _named_colors.find(name); - ERR_FAIL_NULL_V_MSG(color, Color(), "Invalid color name: " + p_name + "."); - return color->value(); + int idx = 0; + while (named_colors[idx].name != nullptr) { + if (name == named_colors[idx].name) { + return named_colors[idx].color; + } + idx++; + } + + ERR_FAIL_V_MSG(Color(), "Invalid color name: " + p_name + "."); + + return Color(); +} + +int Color::get_named_color_count() { + int idx = 0; + while (named_colors[idx].name != nullptr) { + idx++; + } + return idx; +} +String Color::get_named_color_name(int p_idx) { + return named_colors[p_idx].name; +} +Color Color::get_named_color(int p_idx) { + return named_colors[p_idx].color; } String _to_hex(float p_val) { @@ -482,6 +489,13 @@ Color Color::operator+(const Color &p_color) const { a + p_color.a); } +void Color::operator+=(const Color &p_color) { + r = r + p_color.r; + g = g + p_color.g; + b = b + p_color.b; + a = a + p_color.a; +} + Color Color::operator-(const Color &p_color) const { return Color( r - p_color.r, @@ -505,12 +519,12 @@ Color Color::operator*(const Color &p_color) const { a * p_color.a); } -Color Color::operator*(const real_t &rvalue) const { +Color Color::operator*(real_t p_rvalue) const { return Color( - r * rvalue, - g * rvalue, - b * rvalue, - a * rvalue); + r * p_rvalue, + g * p_rvalue, + b * p_rvalue, + a * p_rvalue); } void Color::operator*=(const Color &p_color) { @@ -520,11 +534,11 @@ void Color::operator*=(const Color &p_color) { a = a * p_color.a; } -void Color::operator*=(const real_t &rvalue) { - r = r * rvalue; - g = g * rvalue; - b = b * rvalue; - a = a * rvalue; +void Color::operator*=(real_t p_rvalue) { + r = r * p_rvalue; + g = g * p_rvalue; + b = b * p_rvalue; + a = a * p_rvalue; } Color Color::operator/(const Color &p_color) const { @@ -535,12 +549,12 @@ Color Color::operator/(const Color &p_color) const { a / p_color.a); } -Color Color::operator/(const real_t &rvalue) const { +Color Color::operator/(real_t p_rvalue) const { return Color( - r / rvalue, - g / rvalue, - b / rvalue, - a / rvalue); + r / p_rvalue, + g / p_rvalue, + b / p_rvalue, + a / p_rvalue); } void Color::operator/=(const Color &p_color) { @@ -550,17 +564,17 @@ void Color::operator/=(const Color &p_color) { a = a / p_color.a; } -void Color::operator/=(const real_t &rvalue) { - if (rvalue == 0) { +void Color::operator/=(real_t p_rvalue) { + if (p_rvalue == 0) { r = 1.0; g = 1.0; b = 1.0; a = 1.0; } else { - r = r / rvalue; - g = g / rvalue; - b = b / rvalue; - a = a / rvalue; + r = r / p_rvalue; + g = g / p_rvalue; + b = b / p_rvalue; + a = a / p_rvalue; } } diff --git a/core/color.h b/core/math/color.h index 2dbbc52905..c7b5ceca3d 100644 --- a/core/color.h +++ b/core/math/color.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,7 @@ #define COLOR_H #include "core/math/math_funcs.h" -#include "core/ustring.h" +#include "core/string/ustring.h" struct Color { union { @@ -45,9 +45,6 @@ struct Color { float components[4] = { 0, 0, 0, 1.0 }; }; - bool operator==(const Color &p_color) const { return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a); } - bool operator!=(const Color &p_color) const { return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a); } - uint32_t to_rgba32() const; uint32_t to_argb32() const; uint32_t to_abgr32() const; @@ -59,49 +56,49 @@ struct Color { float get_v() const; void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0); - _FORCE_INLINE_ float &operator[](int idx) { - return components[idx]; + _FORCE_INLINE_ float &operator[](int p_idx) { + return components[p_idx]; } - _FORCE_INLINE_ const float &operator[](int idx) const { - return components[idx]; + _FORCE_INLINE_ const float &operator[](int p_idx) const { + return components[p_idx]; } - Color operator+(const Color &p_color) const; - _FORCE_INLINE_ void operator+=(const Color &p_color) { - r = r + p_color.r; - g = g + p_color.g; - b = b + p_color.b; - a = a + p_color.a; + bool operator==(const Color &p_color) const { + return (r == p_color.r && g == p_color.g && b == p_color.b && a == p_color.a); } + bool operator!=(const Color &p_color) const { + return (r != p_color.r || g != p_color.g || b != p_color.b || a != p_color.a); + } + + Color operator+(const Color &p_color) const; + void operator+=(const Color &p_color); Color operator-() const; Color operator-(const Color &p_color) const; void operator-=(const Color &p_color); Color operator*(const Color &p_color) const; - Color operator*(const real_t &rvalue) const; + Color operator*(real_t p_rvalue) const; void operator*=(const Color &p_color); - void operator*=(const real_t &rvalue); + void operator*=(real_t p_rvalue); Color operator/(const Color &p_color) const; - Color operator/(const real_t &rvalue) const; + Color operator/(real_t p_rvalue) const; void operator/=(const Color &p_color); - void operator/=(const real_t &rvalue); + void operator/=(real_t p_rvalue); bool is_equal_approx(const Color &p_color) const; void invert(); - void contrast(); Color inverted() const; - Color contrasted() const; - _FORCE_INLINE_ Color lerp(const Color &p_b, float p_t) const { + _FORCE_INLINE_ Color lerp(const Color &p_to, float p_weight) const { Color res = *this; - res.r += (p_t * (p_b.r - r)); - res.g += (p_t * (p_b.g - g)); - res.b += (p_t * (p_b.b - b)); - res.a += (p_t * (p_b.a - a)); + res.r += (p_weight * (p_to.r - r)); + res.g += (p_weight * (p_to.g - g)); + res.b += (p_weight * (p_to.b - b)); + res.a += (p_weight * (p_to.a - a)); return res; } @@ -125,10 +122,9 @@ struct Color { _FORCE_INLINE_ uint32_t to_rgbe9995() const { const float pow2to9 = 512.0f; const float B = 15.0f; - //const float Emax = 31.0f; const float N = 9.0f; - float sharedexp = 65408.000f; //(( pow2to9 - 1.0f)/ pow2to9)*powf( 2.0f, 31.0f - 15.0f); + float sharedexp = 65408.000f; // Result of: ((pow2to9 - 1.0f) / pow2to9) * powf(2.0f, 31.0f - 15.0f) float cRed = MAX(0.0f, MIN(sharedexp, r)); float cGreen = MAX(0.0f, MIN(sharedexp, g)); @@ -136,8 +132,6 @@ struct Color { float cMax = MAX(cRed, MAX(cGreen, cBlue)); - // expp = MAX(-B - 1, log2(maxc)) + 1 + B - float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / Math_LN2)) + 1.0f + B; float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f); @@ -188,6 +182,9 @@ struct Color { static Color html(const String &p_rgba); static bool html_is_valid(const String &p_color); static Color named(const String &p_name); + static int get_named_color_count(); + static String get_named_color_name(int p_idx); + static Color get_named_color(int p_idx); String to_html(bool p_alpha = true) const; Color from_hsv(float p_h, float p_s, float p_v, float p_a) const; static Color from_rgbe9995(uint32_t p_rgbe); @@ -195,12 +192,27 @@ struct Color { _FORCE_INLINE_ bool operator<(const Color &p_color) const; //used in set keys operator String() const; + // For the binder. + _FORCE_INLINE_ void set_r8(int32_t r8) { r = (CLAMP(r8, 0, 255) / 255.0); } + _FORCE_INLINE_ int32_t get_r8() const { return int32_t(CLAMP(r * 255.0, 0.0, 255.0)); } + _FORCE_INLINE_ void set_g8(int32_t g8) { g = (CLAMP(g8, 0, 255) / 255.0); } + _FORCE_INLINE_ int32_t get_g8() const { return int32_t(CLAMP(g * 255.0, 0.0, 255.0)); } + _FORCE_INLINE_ void set_b8(int32_t b8) { b = (CLAMP(b8, 0, 255) / 255.0); } + _FORCE_INLINE_ int32_t get_b8() const { return int32_t(CLAMP(b * 255.0, 0.0, 255.0)); } + _FORCE_INLINE_ void set_a8(int32_t a8) { a = (CLAMP(a8, 0, 255) / 255.0); } + _FORCE_INLINE_ int32_t get_a8() const { return int32_t(CLAMP(a * 255.0, 0.0, 255.0)); } + + _FORCE_INLINE_ void set_h(float p_h) { set_hsv(p_h, get_s(), get_v()); } + _FORCE_INLINE_ void set_s(float p_s) { set_hsv(get_h(), p_s, get_v()); } + _FORCE_INLINE_ void set_v(float p_v) { set_hsv(get_h(), get_s(), p_v); } + _FORCE_INLINE_ Color() {} /** - * RGB / RGBA construct parameters. Alpha is optional, but defaults to 1.0 + * RGBA construct parameters. + * Alpha is not optional as otherwise we can't bind the RGB version for scripting. */ - _FORCE_INLINE_ Color(float p_r, float p_g, float p_b, float p_a = 1.0) { + _FORCE_INLINE_ Color(float p_r, float p_g, float p_b, float p_a) { r = p_r; g = p_g; b = p_b; @@ -208,6 +220,16 @@ struct Color { } /** + * RGB construct parameters. + */ + _FORCE_INLINE_ Color(float p_r, float p_g, float p_b) { + r = p_r; + g = p_g; + b = p_b; + a = 1.0; + } + + /** * Construct a Color from another Color, but with the specified alpha value. */ _FORCE_INLINE_ Color(const Color &p_c, float p_a) { @@ -234,7 +256,7 @@ bool Color::operator<(const Color &p_color) const { } } -_FORCE_INLINE_ Color operator*(const real_t &p_real, const Color &p_color) { +_FORCE_INLINE_ Color operator*(real_t p_real, const Color &p_color) { return p_color * p_real; } diff --git a/core/math/color_names.inc b/core/math/color_names.inc new file mode 100644 index 0000000000..523c7e3c59 --- /dev/null +++ b/core/math/color_names.inc @@ -0,0 +1,160 @@ +// Names from https://en.wikipedia.org/wiki/X11_color_names + +// So this in a way that does not require memory allocation +// the old way leaked memory +// this is not used as often as for more performance to make sense + +struct NamedColor { + const char *name; + Color color; +}; + +static NamedColor named_colors[] = { + { "aliceblue", Color(0.94, 0.97, 1.00) }, + { "antiquewhite", Color(0.98, 0.92, 0.84) }, + { "aqua", Color(0.00, 1.00, 1.00) }, + { "aquamarine", Color(0.50, 1.00, 0.83) }, + { "azure", Color(0.94, 1.00, 1.00) }, + { "beige", Color(0.96, 0.96, 0.86) }, + { "bisque", Color(1.00, 0.89, 0.77) }, + { "black", Color(0.00, 0.00, 0.00) }, + { "blanchedalmond", Color(1.00, 0.92, 0.80) }, + { "blue", Color(0.00, 0.00, 1.00) }, + { "blueviolet", Color(0.54, 0.17, 0.89) }, + { "brown", Color(0.65, 0.16, 0.16) }, + { "burlywood", Color(0.87, 0.72, 0.53) }, + { "cadetblue", Color(0.37, 0.62, 0.63) }, + { "chartreuse", Color(0.50, 1.00, 0.00) }, + { "chocolate", Color(0.82, 0.41, 0.12) }, + { "coral", Color(1.00, 0.50, 0.31) }, + { "cornflower", Color(0.39, 0.58, 0.93) }, + { "cornsilk", Color(1.00, 0.97, 0.86) }, + { "crimson", Color(0.86, 0.08, 0.24) }, + { "cyan", Color(0.00, 1.00, 1.00) }, + { "darkblue", Color(0.00, 0.00, 0.55) }, + { "darkcyan", Color(0.00, 0.55, 0.55) }, + { "darkgoldenrod", Color(0.72, 0.53, 0.04) }, + { "darkgray", Color(0.66, 0.66, 0.66) }, + { "darkgreen", Color(0.00, 0.39, 0.00) }, + { "darkkhaki", Color(0.74, 0.72, 0.42) }, + { "darkmagenta", Color(0.55, 0.00, 0.55) }, + { "darkolivegreen", Color(0.33, 0.42, 0.18) }, + { "darkorange", Color(1.00, 0.55, 0.00) }, + { "darkorchid", Color(0.60, 0.20, 0.80) }, + { "darkred", Color(0.55, 0.00, 0.00) }, + { "darksalmon", Color(0.91, 0.59, 0.48) }, + { "darkseagreen", Color(0.56, 0.74, 0.56) }, + { "darkslateblue", Color(0.28, 0.24, 0.55) }, + { "darkslategray", Color(0.18, 0.31, 0.31) }, + { "darkturquoise", Color(0.00, 0.81, 0.82) }, + { "darkviolet", Color(0.58, 0.00, 0.83) }, + { "deeppink", Color(1.00, 0.08, 0.58) }, + { "deepskyblue", Color(0.00, 0.75, 1.00) }, + { "dimgray", Color(0.41, 0.41, 0.41) }, + { "dodgerblue", Color(0.12, 0.56, 1.00) }, + { "firebrick", Color(0.70, 0.13, 0.13) }, + { "floralwhite", Color(1.00, 0.98, 0.94) }, + { "forestgreen", Color(0.13, 0.55, 0.13) }, + { "fuchsia", Color(1.00, 0.00, 1.00) }, + { "gainsboro", Color(0.86, 0.86, 0.86) }, + { "ghostwhite", Color(0.97, 0.97, 1.00) }, + { "gold", Color(1.00, 0.84, 0.00) }, + { "goldenrod", Color(0.85, 0.65, 0.13) }, + { "gray", Color(0.75, 0.75, 0.75) }, + { "green", Color(0.00, 1.00, 0.00) }, + { "greenyellow", Color(0.68, 1.00, 0.18) }, + { "honeydew", Color(0.94, 1.00, 0.94) }, + { "hotpink", Color(1.00, 0.41, 0.71) }, + { "indianred", Color(0.80, 0.36, 0.36) }, + { "indigo", Color(0.29, 0.00, 0.51) }, + { "ivory", Color(1.00, 1.00, 0.94) }, + { "khaki", Color(0.94, 0.90, 0.55) }, + { "lavender", Color(0.90, 0.90, 0.98) }, + { "lavenderblush", Color(1.00, 0.94, 0.96) }, + { "lawngreen", Color(0.49, 0.99, 0.00) }, + { "lemonchiffon", Color(1.00, 0.98, 0.80) }, + { "lightblue", Color(0.68, 0.85, 0.90) }, + { "lightcoral", Color(0.94, 0.50, 0.50) }, + { "lightcyan", Color(0.88, 1.00, 1.00) }, + { "lightgoldenrod", Color(0.98, 0.98, 0.82) }, + { "lightgray", Color(0.83, 0.83, 0.83) }, + { "lightgreen", Color(0.56, 0.93, 0.56) }, + { "lightpink", Color(1.00, 0.71, 0.76) }, + { "lightsalmon", Color(1.00, 0.63, 0.48) }, + { "lightseagreen", Color(0.13, 0.70, 0.67) }, + { "lightskyblue", Color(0.53, 0.81, 0.98) }, + { "lightslategray", Color(0.47, 0.53, 0.60) }, + { "lightsteelblue", Color(0.69, 0.77, 0.87) }, + { "lightyellow", Color(1.00, 1.00, 0.88) }, + { "lime", Color(0.00, 1.00, 0.00) }, + { "limegreen", Color(0.20, 0.80, 0.20) }, + { "linen", Color(0.98, 0.94, 0.90) }, + { "magenta", Color(1.00, 0.00, 1.00) }, + { "maroon", Color(0.69, 0.19, 0.38) }, + { "mediumaquamarine", Color(0.40, 0.80, 0.67) }, + { "mediumblue", Color(0.00, 0.00, 0.80) }, + { "mediumorchid", Color(0.73, 0.33, 0.83) }, + { "mediumpurple", Color(0.58, 0.44, 0.86) }, + { "mediumseagreen", Color(0.24, 0.70, 0.44) }, + { "mediumslateblue", Color(0.48, 0.41, 0.93) }, + { "mediumspringgreen", Color(0.00, 0.98, 0.60) }, + { "mediumturquoise", Color(0.28, 0.82, 0.80) }, + { "mediumvioletred", Color(0.78, 0.08, 0.52) }, + { "midnightblue", Color(0.10, 0.10, 0.44) }, + { "mintcream", Color(0.96, 1.00, 0.98) }, + { "mistyrose", Color(1.00, 0.89, 0.88) }, + { "moccasin", Color(1.00, 0.89, 0.71) }, + { "navajowhite", Color(1.00, 0.87, 0.68) }, + { "navyblue", Color(0.00, 0.00, 0.50) }, + { "oldlace", Color(0.99, 0.96, 0.90) }, + { "olive", Color(0.50, 0.50, 0.00) }, + { "olivedrab", Color(0.42, 0.56, 0.14) }, + { "orange", Color(1.00, 0.65, 0.00) }, + { "orangered", Color(1.00, 0.27, 0.00) }, + { "orchid", Color(0.85, 0.44, 0.84) }, + { "palegoldenrod", Color(0.93, 0.91, 0.67) }, + { "palegreen", Color(0.60, 0.98, 0.60) }, + { "paleturquoise", Color(0.69, 0.93, 0.93) }, + { "palevioletred", Color(0.86, 0.44, 0.58) }, + { "papayawhip", Color(1.00, 0.94, 0.84) }, + { "peachpuff", Color(1.00, 0.85, 0.73) }, + { "peru", Color(0.80, 0.52, 0.25) }, + { "pink", Color(1.00, 0.75, 0.80) }, + { "plum", Color(0.87, 0.63, 0.87) }, + { "powderblue", Color(0.69, 0.88, 0.90) }, + { "purple", Color(0.63, 0.13, 0.94) }, + { "rebeccapurple", Color(0.40, 0.20, 0.60) }, + { "red", Color(1.00, 0.00, 0.00) }, + { "rosybrown", Color(0.74, 0.56, 0.56) }, + { "royalblue", Color(0.25, 0.41, 0.88) }, + { "saddlebrown", Color(0.55, 0.27, 0.07) }, + { "salmon", Color(0.98, 0.50, 0.45) }, + { "sandybrown", Color(0.96, 0.64, 0.38) }, + { "seagreen", Color(0.18, 0.55, 0.34) }, + { "seashell", Color(1.00, 0.96, 0.93) }, + { "sienna", Color(0.63, 0.32, 0.18) }, + { "silver", Color(0.75, 0.75, 0.75) }, + { "skyblue", Color(0.53, 0.81, 0.92) }, + { "slateblue", Color(0.42, 0.35, 0.80) }, + { "slategray", Color(0.44, 0.50, 0.56) }, + { "snow", Color(1.00, 0.98, 0.98) }, + { "springgreen", Color(0.00, 1.00, 0.50) }, + { "steelblue", Color(0.27, 0.51, 0.71) }, + { "tan", Color(0.82, 0.71, 0.55) }, + { "teal", Color(0.00, 0.50, 0.50) }, + { "thistle", Color(0.85, 0.75, 0.85) }, + { "tomato", Color(1.00, 0.39, 0.28) }, + { "transparent", Color(1.00, 1.00, 1.00, 0.00) }, + { "turquoise", Color(0.25, 0.88, 0.82) }, + { "violet", Color(0.93, 0.51, 0.93) }, + { "webgray", Color(0.50, 0.50, 0.50) }, + { "webgreen", Color(0.00, 0.50, 0.00) }, + { "webmaroon", Color(0.50, 0.00, 0.00) }, + { "webpurple", Color(0.50, 0.00, 0.50) }, + { "wheat", Color(0.96, 0.87, 0.70) }, + { "white", Color(1.00, 1.00, 1.00) }, + { "whitesmoke", Color(0.96, 0.96, 0.96) }, + { "yellow", Color(1.00, 1.00, 0.00) }, + { "yellowgreen", Color(0.60, 0.80, 0.20) }, + { nullptr, Color(0.60, 0.80, 0.20) }, +}; diff --git a/core/math/delaunay_2d.h b/core/math/delaunay_2d.h index d637671686..95064e5700 100644 --- a/core/math/delaunay_2d.h +++ b/core/math/delaunay_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h index 014b4c4621..25cc1125db 100644 --- a/core/math/delaunay_3d.h +++ b/core/math/delaunay_3d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,15 +31,15 @@ #ifndef DELAUNAY_3D_H #define DELAUNAY_3D_H -#include "core/local_vector.h" #include "core/math/aabb.h" #include "core/math/camera_matrix.h" #include "core/math/vector3.h" -#include "core/oa_hash_map.h" #include "core/os/file_access.h" -#include "core/print_string.h" -#include "core/variant.h" -#include "core/vector.h" +#include "core/string/print_string.h" +#include "core/templates/local_vector.h" +#include "core/templates/oa_hash_map.h" +#include "core/templates/vector.h" +#include "core/variant/variant.h" #include "thirdparty/misc/r128.h" diff --git a/core/math/disjoint_set.h b/core/math/disjoint_set.h index 198f46e111..b155412f64 100644 --- a/core/math/disjoint_set.h +++ b/core/math/disjoint_set.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef DISJOINT_SET_H #define DISJOINT_SET_H -#include "core/map.h" -#include "core/vector.h" +#include "core/templates/map.h" +#include "core/templates/vector.h" /** @author Marios Staikopoulos <marios@staik.net> diff --git a/core/math/dynamic_bvh.cpp b/core/math/dynamic_bvh.cpp new file mode 100644 index 0000000000..4639a52278 --- /dev/null +++ b/core/math/dynamic_bvh.cpp @@ -0,0 +1,431 @@ +/*************************************************************************/ +/* dynamic_bvh.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "dynamic_bvh.h" + +void DynamicBVH::_delete_node(Node *p_node) { + node_allocator.free(p_node); +} + +void DynamicBVH::_recurse_delete_node(Node *p_node) { + if (!p_node->is_leaf()) { + _recurse_delete_node(p_node->childs[0]); + _recurse_delete_node(p_node->childs[1]); + } + if (p_node == bvh_root) { + bvh_root = nullptr; + } + _delete_node(p_node); +} + +DynamicBVH::Node *DynamicBVH::_create_node(Node *p_parent, void *p_data) { + Node *node = node_allocator.alloc(); + node->parent = p_parent; + node->data = p_data; + return (node); +} + +DynamicBVH::Node *DynamicBVH::_create_node_with_volume(Node *p_parent, const Volume &p_volume, void *p_data) { + Node *node = _create_node(p_parent, p_data); + node->volume = p_volume; + return node; +} + +void DynamicBVH::_insert_leaf(Node *p_root, Node *p_leaf) { + if (!bvh_root) { + bvh_root = p_leaf; + p_leaf->parent = 0; + } else { + if (!p_root->is_leaf()) { + do { + p_root = p_root->childs[p_leaf->volume.select_by_proximity( + p_root->childs[0]->volume, + p_root->childs[1]->volume)]; + } while (!p_root->is_leaf()); + } + Node *prev = p_root->parent; + Node *node = _create_node_with_volume(prev, p_leaf->volume.merge(p_root->volume), 0); + if (prev) { + prev->childs[p_root->get_index_in_parent()] = node; + node->childs[0] = p_root; + p_root->parent = node; + node->childs[1] = p_leaf; + p_leaf->parent = node; + do { + if (!prev->volume.contains(node->volume)) { + prev->volume = prev->childs[0]->volume.merge(prev->childs[1]->volume); + } else { + break; + } + node = prev; + } while (0 != (prev = node->parent)); + } else { + node->childs[0] = p_root; + p_root->parent = node; + node->childs[1] = p_leaf; + p_leaf->parent = node; + bvh_root = node; + } + } +} + +DynamicBVH::Node *DynamicBVH::_remove_leaf(Node *leaf) { + if (leaf == bvh_root) { + bvh_root = 0; + return (0); + } else { + Node *parent = leaf->parent; + Node *prev = parent->parent; + Node *sibling = parent->childs[1 - leaf->get_index_in_parent()]; + if (prev) { + prev->childs[parent->get_index_in_parent()] = sibling; + sibling->parent = prev; + _delete_node(parent); + while (prev) { + const Volume pb = prev->volume; + prev->volume = prev->childs[0]->volume.merge(prev->childs[1]->volume); + if (pb.is_not_equal_to(prev->volume)) { + prev = prev->parent; + } else + break; + } + return (prev ? prev : bvh_root); + } else { + bvh_root = sibling; + sibling->parent = 0; + _delete_node(parent); + return (bvh_root); + } + } +} + +void DynamicBVH::_fetch_leaves(Node *p_root, LocalVector<Node *> &r_leaves, int p_depth) { + if (p_root->is_internal() && p_depth) { + _fetch_leaves(p_root->childs[0], r_leaves, p_depth - 1); + _fetch_leaves(p_root->childs[1], r_leaves, p_depth - 1); + _delete_node(p_root); + } else { + r_leaves.push_back(p_root); + } +} + +// Partitions leaves such that leaves[0, n) are on the +// left of axis, and leaves[n, count) are on the right +// of axis. returns N. +int DynamicBVH::_split(Node **leaves, int p_count, const Vector3 &p_org, const Vector3 &p_axis) { + int begin = 0; + int end = p_count; + for (;;) { + while (begin != end && leaves[begin]->is_left_of_axis(p_org, p_axis)) { + ++begin; + } + + if (begin == end) { + break; + } + + while (begin != end && !leaves[end - 1]->is_left_of_axis(p_org, p_axis)) { + --end; + } + + if (begin == end) { + break; + } + + // swap out of place nodes + --end; + Node *temp = leaves[begin]; + leaves[begin] = leaves[end]; + leaves[end] = temp; + ++begin; + } + + return begin; +} + +DynamicBVH::Volume DynamicBVH::_bounds(Node **leaves, int p_count) { + Volume volume = leaves[0]->volume; + for (int i = 1, ni = p_count; i < ni; ++i) { + volume = volume.merge(leaves[i]->volume); + } + return (volume); +} + +void DynamicBVH::_bottom_up(Node **leaves, int p_count) { + while (p_count > 1) { + real_t minsize = Math_INF; + int minidx[2] = { -1, -1 }; + for (int i = 0; i < p_count; ++i) { + for (int j = i + 1; j < p_count; ++j) { + const real_t sz = leaves[i]->volume.merge(leaves[j]->volume).get_size(); + if (sz < minsize) { + minsize = sz; + minidx[0] = i; + minidx[1] = j; + } + } + } + Node *n[] = { leaves[minidx[0]], leaves[minidx[1]] }; + Node *p = _create_node_with_volume(nullptr, n[0]->volume.merge(n[1]->volume), nullptr); + p->childs[0] = n[0]; + p->childs[1] = n[1]; + n[0]->parent = p; + n[1]->parent = p; + leaves[minidx[0]] = p; + leaves[minidx[1]] = leaves[p_count - 1]; + --p_count; + } +} + +DynamicBVH::Node *DynamicBVH::_top_down(Node **leaves, int p_count, int p_bu_threshold) { + static const Vector3 axis[] = { Vector3(1, 0, 0), Vector3(0, 1, 0), Vector3(0, 0, 1) }; + + ERR_FAIL_COND_V(p_bu_threshold <= 1, nullptr); + if (p_count > 1) { + if (p_count > p_bu_threshold) { + const Volume vol = _bounds(leaves, p_count); + const Vector3 org = vol.get_center(); + int partition; + int bestaxis = -1; + int bestmidp = p_count; + int splitcount[3][2] = { { 0, 0 }, { 0, 0 }, { 0, 0 } }; + int i; + for (i = 0; i < p_count; ++i) { + const Vector3 x = leaves[i]->volume.get_center() - org; + for (int j = 0; j < 3; ++j) { + ++splitcount[j][x.dot(axis[j]) > 0 ? 1 : 0]; + } + } + for (i = 0; i < 3; ++i) { + if ((splitcount[i][0] > 0) && (splitcount[i][1] > 0)) { + const int midp = (int)Math::abs(real_t(splitcount[i][0] - splitcount[i][1])); + if (midp < bestmidp) { + bestaxis = i; + bestmidp = midp; + } + } + } + if (bestaxis >= 0) { + partition = _split(leaves, p_count, org, axis[bestaxis]); + ERR_FAIL_COND_V(partition == 0 || partition == p_count, nullptr); + } else { + partition = p_count / 2 + 1; + } + + Node *node = _create_node_with_volume(nullptr, vol, nullptr); + node->childs[0] = _top_down(&leaves[0], partition, p_bu_threshold); + node->childs[1] = _top_down(&leaves[partition], p_count - partition, p_bu_threshold); + node->childs[0]->parent = node; + node->childs[1]->parent = node; + return (node); + } else { + _bottom_up(leaves, p_count); + return (leaves[0]); + } + } + return (leaves[0]); +} + +DynamicBVH::Node *DynamicBVH::_node_sort(Node *n, Node *&r) { + Node *p = n->parent; + ERR_FAIL_COND_V(!n->is_internal(), nullptr); + if (p > n) { + const int i = n->get_index_in_parent(); + const int j = 1 - i; + Node *s = p->childs[j]; + Node *q = p->parent; + ERR_FAIL_COND_V(n != p->childs[i], nullptr); + if (q) + q->childs[p->get_index_in_parent()] = n; + else + r = n; + s->parent = n; + p->parent = n; + n->parent = q; + p->childs[0] = n->childs[0]; + p->childs[1] = n->childs[1]; + n->childs[0]->parent = p; + n->childs[1]->parent = p; + n->childs[i] = p; + n->childs[j] = s; + SWAP(p->volume, n->volume); + return (p); + } + return (n); +} + +void DynamicBVH::clear() { + if (bvh_root) { + _recurse_delete_node(bvh_root); + } + lkhd = -1; + opath = 0; +} + +void DynamicBVH::optimize_bottom_up() { + if (bvh_root) { + LocalVector<Node *> leaves; + _fetch_leaves(bvh_root, leaves); + _bottom_up(&leaves[0], leaves.size()); + bvh_root = leaves[0]; + } +} + +void DynamicBVH::optimize_top_down(int bu_threshold) { + if (bvh_root) { + LocalVector<Node *> leaves; + _fetch_leaves(bvh_root, leaves); + bvh_root = _top_down(&leaves[0], leaves.size(), bu_threshold); + } +} + +void DynamicBVH::optimize_incremental(int passes) { + if (passes < 0) + passes = total_leaves; + if (bvh_root && (passes > 0)) { + do { + Node *node = bvh_root; + unsigned bit = 0; + while (node->is_internal()) { + node = _node_sort(node, bvh_root)->childs[(opath >> bit) & 1]; + bit = (bit + 1) & (sizeof(unsigned) * 8 - 1); + } + _update(node); + ++opath; + } while (--passes); + } +} + +DynamicBVH::ID DynamicBVH::insert(const AABB &p_box, void *p_userdata) { + Volume volume; + volume.min = p_box.position; + volume.max = p_box.position + p_box.size; + + Node *leaf = _create_node_with_volume(nullptr, volume, p_userdata); + _insert_leaf(bvh_root, leaf); + ++total_leaves; + + ID id; + id.node = leaf; + + return id; +} + +void DynamicBVH::_update(Node *leaf, int lookahead) { + Node *root = _remove_leaf(leaf); + if (root) { + if (lookahead >= 0) { + for (int i = 0; (i < lookahead) && root->parent; ++i) { + root = root->parent; + } + } else + root = bvh_root; + } + _insert_leaf(root, leaf); +} + +bool DynamicBVH::update(const ID &p_id, const AABB &p_box) { + ERR_FAIL_COND_V(!p_id.is_valid(), false); + Node *leaf = p_id.node; + + Volume volume; + volume.min = p_box.position; + volume.max = p_box.position + p_box.size; + + if (leaf->volume.min.is_equal_approx(volume.min) && leaf->volume.max.is_equal_approx(volume.max)) { + // noop + return false; + } + + Node *base = _remove_leaf(leaf); + if (base) { + if (lkhd >= 0) { + for (int i = 0; (i < lkhd) && base->parent; ++i) { + base = base->parent; + } + } else + base = bvh_root; + } + leaf->volume = volume; + _insert_leaf(base, leaf); + return true; +} + +void DynamicBVH::remove(const ID &p_id) { + ERR_FAIL_COND(!p_id.is_valid()); + Node *leaf = p_id.node; + _remove_leaf(leaf); + _delete_node(leaf); + --total_leaves; +} + +void DynamicBVH::_extract_leaves(Node *p_node, List<ID> *r_elements) { + if (p_node->is_internal()) { + _extract_leaves(p_node->childs[0], r_elements); + _extract_leaves(p_node->childs[1], r_elements); + } else { + ID id; + id.node = p_node; + r_elements->push_back(id); + } +} + +void DynamicBVH::set_index(uint32_t p_index) { + ERR_FAIL_COND(bvh_root != nullptr); + index = p_index; +} + +uint32_t DynamicBVH::get_index() const { + return index; +} + +void DynamicBVH::get_elements(List<ID> *r_elements) { + if (bvh_root) { + _extract_leaves(bvh_root, r_elements); + } +} + +int DynamicBVH::get_leaf_count() const { + return total_leaves; +} +int DynamicBVH::get_max_depth() const { + if (bvh_root) { + int depth = 1; + int max_depth = 0; + bvh_root->get_max_depth(depth, max_depth); + return max_depth; + } else { + return 0; + } +} + +DynamicBVH::~DynamicBVH() { + clear(); +} diff --git a/core/math/dynamic_bvh.h b/core/math/dynamic_bvh.h new file mode 100644 index 0000000000..c71db2d24d --- /dev/null +++ b/core/math/dynamic_bvh.h @@ -0,0 +1,468 @@ +/*************************************************************************/ +/* dynamic_bvh.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef DYNAMICBVH_H +#define DYNAMICBVH_H + +#include "core/math/aabb.h" +#include "core/templates/list.h" +#include "core/templates/local_vector.h" +#include "core/templates/paged_allocator.h" +#include "core/typedefs.h" + +// Based on bullet Dbvh + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///DynamicBVH implementation by Nathanael Presson +// The DynamicBVH class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree). + +class DynamicBVH { + struct Node; + +public: + struct ID { + Node *node = nullptr; + + public: + _FORCE_INLINE_ bool is_valid() const { return node != nullptr; } + }; + +private: + struct Volume { + Vector3 min, max; + + _FORCE_INLINE_ Vector3 get_center() const { return ((min + max) / 2); } + _FORCE_INLINE_ Vector3 get_length() const { return (max - min); } + + _FORCE_INLINE_ bool contains(const Volume &a) const { + return ((min.x <= a.min.x) && + (min.y <= a.min.y) && + (min.z <= a.min.z) && + (max.x >= a.max.x) && + (max.y >= a.max.y) && + (max.z >= a.max.z)); + } + + _FORCE_INLINE_ Volume merge(const Volume &b) const { + Volume r; + for (int i = 0; i < 3; ++i) { + if (min[i] < b.min[i]) + r.min[i] = min[i]; + else + r.min[i] = b.min[i]; + if (max[i] > b.max[i]) + r.max[i] = max[i]; + else + r.max[i] = b.max[i]; + } + return r; + } + + _FORCE_INLINE_ real_t get_size() const { + const Vector3 edges = get_length(); + return (edges.x * edges.y * edges.z + + edges.x + edges.y + edges.z); + } + + _FORCE_INLINE_ bool is_not_equal_to(const Volume &b) const { + return ((min.x != b.min.x) || + (min.y != b.min.y) || + (min.z != b.min.z) || + (max.x != b.max.x) || + (max.y != b.max.y) || + (max.z != b.max.z)); + } + + _FORCE_INLINE_ real_t get_proximity_to(const Volume &b) const { + const Vector3 d = (min + max) - (b.min + b.max); + return (Math::abs(d.x) + Math::abs(d.y) + Math::abs(d.z)); + } + + _FORCE_INLINE_ int select_by_proximity(const Volume &a, const Volume &b) const { + return (get_proximity_to(a) < get_proximity_to(b) ? 0 : 1); + } + + // + _FORCE_INLINE_ bool intersects(const Volume &b) const { + return ((min.x <= b.max.x) && + (max.x >= b.min.x) && + (min.y <= b.max.y) && + (max.y >= b.min.y) && + (min.z <= b.max.z) && + (max.z >= b.min.z)); + } + + _FORCE_INLINE_ bool intersects_convex(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const { + Vector3 half_extents = (max - min) * 0.5; + Vector3 ofs = min + half_extents; + + for (int i = 0; i < p_plane_count; i++) { + const Plane &p = p_planes[i]; + Vector3 point( + (p.normal.x > 0) ? -half_extents.x : half_extents.x, + (p.normal.y > 0) ? -half_extents.y : half_extents.y, + (p.normal.z > 0) ? -half_extents.z : half_extents.z); + point += ofs; + if (p.is_point_over(point)) { + return false; + } + } + + // Make sure all points in the shape aren't fully separated from the AABB on + // each axis. + int bad_point_counts_positive[3] = { 0 }; + int bad_point_counts_negative[3] = { 0 }; + + for (int k = 0; k < 3; k++) { + for (int i = 0; i < p_point_count; i++) { + if (p_points[i].coord[k] > ofs.coord[k] + half_extents.coord[k]) { + bad_point_counts_positive[k]++; + } + if (p_points[i].coord[k] < ofs.coord[k] - half_extents.coord[k]) { + bad_point_counts_negative[k]++; + } + } + + if (bad_point_counts_negative[k] == p_point_count) { + return false; + } + if (bad_point_counts_positive[k] == p_point_count) { + return false; + } + } + + return true; + } + }; + + struct Node { + Volume volume; + Node *parent = nullptr; + union { + Node *childs[2]; + void *data; + }; + + _FORCE_INLINE_ bool is_leaf() const { return childs[1] == nullptr; } + _FORCE_INLINE_ bool is_internal() const { return (!is_leaf()); } + + _FORCE_INLINE_ int get_index_in_parent() const { + ERR_FAIL_COND_V(!parent, 0); + return (parent->childs[1] == this) ? 1 : 0; + } + void get_max_depth(int depth, int &maxdepth) { + if (is_internal()) { + childs[0]->get_max_depth(depth + 1, maxdepth); + childs[1]->get_max_depth(depth + 1, maxdepth); + } else { + maxdepth = MAX(maxdepth, depth); + } + } + + // + int count_leaves() const { + if (is_internal()) + return childs[0]->count_leaves() + childs[1]->count_leaves(); + else + return (1); + } + + bool is_left_of_axis(const Vector3 &org, const Vector3 &axis) const { + return axis.dot(volume.get_center() - org) <= 0; + } + + Node() { + childs[0] = nullptr; + childs[1] = nullptr; + } + }; + + PagedAllocator<Node> node_allocator; + // Fields + Node *bvh_root = nullptr; + int lkhd = -1; + int total_leaves = 0; + uint32_t opath = 0; + uint32_t index = 0; + + enum { + ALLOCA_STACK_SIZE = 128 + }; + + _FORCE_INLINE_ void _delete_node(Node *p_node); + void _recurse_delete_node(Node *p_node); + _FORCE_INLINE_ Node *_create_node(Node *p_parent, void *p_data); + _FORCE_INLINE_ DynamicBVH::Node *_create_node_with_volume(Node *p_parent, const Volume &p_volume, void *p_data); + _FORCE_INLINE_ void _insert_leaf(Node *p_root, Node *p_leaf); + _FORCE_INLINE_ Node *_remove_leaf(Node *leaf); + void _fetch_leaves(Node *p_root, LocalVector<Node *> &r_leaves, int p_depth = -1); + static int _split(Node **leaves, int p_count, const Vector3 &p_org, const Vector3 &p_axis); + static Volume _bounds(Node **leaves, int p_count); + void _bottom_up(Node **leaves, int p_count); + Node *_top_down(Node **leaves, int p_count, int p_bu_threshold); + Node *_node_sort(Node *n, Node *&r); + + _FORCE_INLINE_ void _update(Node *leaf, int lookahead = -1); + + void _extract_leaves(Node *p_node, List<ID> *r_elements); + + _FORCE_INLINE_ bool _ray_aabb(const Vector3 &rayFrom, const Vector3 &rayInvDirection, const unsigned int raySign[3], const Vector3 bounds[2], real_t &tmin, real_t lambda_min, real_t lambda_max) { + real_t tmax, tymin, tymax, tzmin, tzmax; + tmin = (bounds[raySign[0]].x - rayFrom.x) * rayInvDirection.x; + tmax = (bounds[1 - raySign[0]].x - rayFrom.x) * rayInvDirection.x; + tymin = (bounds[raySign[1]].y - rayFrom.y) * rayInvDirection.y; + tymax = (bounds[1 - raySign[1]].y - rayFrom.y) * rayInvDirection.y; + + if ((tmin > tymax) || (tymin > tmax)) + return false; + + if (tymin > tmin) + tmin = tymin; + + if (tymax < tmax) + tmax = tymax; + + tzmin = (bounds[raySign[2]].z - rayFrom.z) * rayInvDirection.z; + tzmax = (bounds[1 - raySign[2]].z - rayFrom.z) * rayInvDirection.z; + + if ((tmin > tzmax) || (tzmin > tmax)) + return false; + if (tzmin > tmin) + tmin = tzmin; + if (tzmax < tmax) + tmax = tzmax; + return ((tmin < lambda_max) && (tmax > lambda_min)); + } + +public: + // Methods + void clear(); + bool is_empty() const { return (0 == bvh_root); } + void optimize_bottom_up(); + void optimize_top_down(int bu_threshold = 128); + void optimize_incremental(int passes); + ID insert(const AABB &p_box, void *p_userdata); + bool update(const ID &p_id, const AABB &p_box); + void remove(const ID &p_id); + void get_elements(List<ID> *r_elements); + + int get_leaf_count() const; + int get_max_depth() const; + + /* Discouraged, but works as a reference on how it must be used */ + struct DefaultQueryResult { + virtual bool operator()(void *p_data) = 0; //return true whether you want to continue the query + virtual ~DefaultQueryResult() {} + }; + + template <class QueryResult> + _FORCE_INLINE_ void aabb_query(const AABB &p_aabb, QueryResult &r_result); + template <class QueryResult> + _FORCE_INLINE_ void convex_query(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count, QueryResult &r_result); + template <class QueryResult> + _FORCE_INLINE_ void ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResult &r_result); + + void set_index(uint32_t p_index); + uint32_t get_index() const; + + ~DynamicBVH(); +}; + +template <class QueryResult> +void DynamicBVH::aabb_query(const AABB &p_box, QueryResult &r_result) { + if (!bvh_root) { + return; + } + + Volume volume; + volume.min = p_box.position; + volume.max = p_box.position + p_box.size; + + const Node **stack = (const Node **)alloca(ALLOCA_STACK_SIZE * sizeof(const Node *)); + stack[0] = bvh_root; + int32_t depth = 1; + int32_t threshold = ALLOCA_STACK_SIZE - 2; + + LocalVector<const Node *> aux_stack; //only used in rare occasions when you run out of alloca memory because tree is too unbalanced. Should correct itself over time. + + do { + depth--; + const Node *n = stack[depth]; + if (n->volume.intersects(volume)) { + if (n->is_internal()) { + if (depth > threshold) { + if (aux_stack.is_empty()) { + aux_stack.resize(ALLOCA_STACK_SIZE * 2); + copymem(aux_stack.ptr(), stack, ALLOCA_STACK_SIZE * sizeof(const Node *)); + } else { + aux_stack.resize(aux_stack.size() * 2); + } + stack = aux_stack.ptr(); + threshold = aux_stack.size() - 2; + } + stack[depth++] = n->childs[0]; + stack[depth++] = n->childs[1]; + } else { + if (r_result(n->data)) { + return; + } + } + } + } while (depth > 0); +} + +template <class QueryResult> +void DynamicBVH::convex_query(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count, QueryResult &r_result) { + if (!bvh_root) { + return; + } + + //generate a volume anyway to improve pre-testing + Volume volume; + for (int i = 0; i < p_point_count; i++) { + if (i == 0) { + volume.min = p_points[0]; + volume.max = p_points[0]; + } else { + volume.min.x = MIN(volume.min.x, p_points[i].x); + volume.min.y = MIN(volume.min.y, p_points[i].y); + volume.min.z = MIN(volume.min.z, p_points[i].z); + + volume.max.x = MAX(volume.max.x, p_points[i].x); + volume.max.y = MAX(volume.max.y, p_points[i].y); + volume.max.z = MAX(volume.max.z, p_points[i].z); + } + } + + const Node **stack = (const Node **)alloca(ALLOCA_STACK_SIZE * sizeof(const Node *)); + stack[0] = bvh_root; + int32_t depth = 1; + int32_t threshold = ALLOCA_STACK_SIZE - 2; + + LocalVector<const Node *> aux_stack; //only used in rare occasions when you run out of alloca memory because tree is too unbalanced. Should correct itself over time. + + do { + depth--; + const Node *n = stack[depth]; + if (n->volume.intersects(volume) && n->volume.intersects_convex(p_planes, p_plane_count, p_points, p_point_count)) { + if (n->is_internal()) { + if (depth > threshold) { + if (aux_stack.is_empty()) { + aux_stack.resize(ALLOCA_STACK_SIZE * 2); + copymem(aux_stack.ptr(), stack, ALLOCA_STACK_SIZE * sizeof(const Node *)); + } else { + aux_stack.resize(aux_stack.size() * 2); + } + stack = aux_stack.ptr(); + threshold = aux_stack.size() - 2; + } + stack[depth++] = n->childs[0]; + stack[depth++] = n->childs[1]; + } else { + if (r_result(n->data)) { + return; + } + } + } + } while (depth > 0); +} +template <class QueryResult> +void DynamicBVH::ray_query(const Vector3 &p_from, const Vector3 &p_to, QueryResult &r_result) { + if (!bvh_root) { + return; + } + + Vector3 ray_dir = (p_to - p_from); + ray_dir.normalize(); + + ///what about division by zero? --> just set rayDirection[i] to INF/B3_LARGE_FLOAT + Vector3 inv_dir; + inv_dir[0] = ray_dir[0] == real_t(0.0) ? real_t(1e20) : real_t(1.0) / ray_dir[0]; + inv_dir[1] = ray_dir[1] == real_t(0.0) ? real_t(1e20) : real_t(1.0) / ray_dir[1]; + inv_dir[2] = ray_dir[2] == real_t(0.0) ? real_t(1e20) : real_t(1.0) / ray_dir[2]; + unsigned int signs[3] = { inv_dir[0] < 0.0, inv_dir[1] < 0.0, inv_dir[2] < 0.0 }; + + real_t lambda_max = ray_dir.dot(p_to - p_from); + + Vector3 bounds[2]; + + const Node **stack = (const Node **)alloca(ALLOCA_STACK_SIZE * sizeof(const Node *)); + stack[0] = bvh_root; + int32_t depth = 1; + int32_t threshold = ALLOCA_STACK_SIZE - 2; + + LocalVector<const Node *> aux_stack; //only used in rare occasions when you run out of alloca memory because tree is too unbalanced. Should correct itself over time. + + do { + depth--; + const Node *node = stack[depth]; + bounds[0] = node->volume.min; + bounds[1] = node->volume.max; + real_t tmin = 1.f, lambda_min = 0.f; + unsigned int result1 = false; + result1 = _ray_aabb(p_from, inv_dir, signs, bounds, tmin, lambda_min, lambda_max); + if (result1) { + if (node->is_internal()) { + if (depth > threshold) { + if (aux_stack.is_empty()) { + aux_stack.resize(ALLOCA_STACK_SIZE * 2); + copymem(aux_stack.ptr(), stack, ALLOCA_STACK_SIZE * sizeof(const Node *)); + } else { + aux_stack.resize(aux_stack.size() * 2); + } + stack = aux_stack.ptr(); + threshold = aux_stack.size() - 2; + } + stack[depth++] = node->childs[0]; + stack[depth++] = node->childs[1]; + } else { + if (r_result(node->data)) { + return; + } + } + } + } while (depth > 0); +} + +#endif // DYNAMICBVH_H diff --git a/core/math/expression.cpp b/core/math/expression.cpp index 1040f9e0e4..636ea601c7 100644 --- a/core/math/expression.cpp +++ b/core/math/expression.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,714 +30,12 @@ #include "expression.h" -#include "core/class_db.h" -#include "core/func_ref.h" #include "core/io/marshalls.h" #include "core/math/math_funcs.h" +#include "core/object/class_db.h" +#include "core/object/reference.h" #include "core/os/os.h" -#include "core/reference.h" -#include "core/variant_parser.h" - -const char *Expression::func_name[Expression::FUNC_MAX] = { - "sin", - "cos", - "tan", - "sinh", - "cosh", - "tanh", - "asin", - "acos", - "atan", - "atan2", - "sqrt", - "fmod", - "fposmod", - "posmod", - "floor", - "ceil", - "round", - "abs", - "sign", - "pow", - "log", - "exp", - "is_nan", - "is_inf", - "ease", - "step_decimals", - "stepify", - "lerp", - "lerp_angle", - "inverse_lerp", - "range_lerp", - "smoothstep", - "move_toward", - "dectime", - "randomize", - "randi", - "randf", - "rand_range", - "seed", - "rand_seed", - "deg2rad", - "rad2deg", - "linear2db", - "db2linear", - "polar2cartesian", - "cartesian2polar", - "wrapi", - "wrapf", - "max", - "min", - "clamp", - "nearest_po2", - "weakref", - "funcref", - "convert", - "typeof", - "type_exists", - "char", - "ord", - "str", - "print", - "printerr", - "printraw", - "var2str", - "str2var", - "var2bytes", - "bytes2var", - "color_named", -}; - -Expression::BuiltinFunc Expression::find_function(const String &p_string) { - for (int i = 0; i < FUNC_MAX; i++) { - if (p_string == func_name[i]) { - return BuiltinFunc(i); - } - } - - return FUNC_MAX; -} - -String Expression::get_func_name(BuiltinFunc p_func) { - ERR_FAIL_INDEX_V(p_func, FUNC_MAX, String()); - return func_name[p_func]; -} - -int Expression::get_func_argument_count(BuiltinFunc p_func) { - switch (p_func) { - case MATH_RANDOMIZE: - case MATH_RAND: - case MATH_RANDF: - return 0; - case MATH_SIN: - case MATH_COS: - case MATH_TAN: - case MATH_SINH: - case MATH_COSH: - case MATH_TANH: - case MATH_ASIN: - case MATH_ACOS: - case MATH_ATAN: - case MATH_SQRT: - case MATH_FLOOR: - case MATH_CEIL: - case MATH_ROUND: - case MATH_ABS: - case MATH_SIGN: - case MATH_LOG: - case MATH_EXP: - case MATH_ISNAN: - case MATH_ISINF: - case MATH_STEP_DECIMALS: - case MATH_SEED: - case MATH_RANDSEED: - case MATH_DEG2RAD: - case MATH_RAD2DEG: - case MATH_LINEAR2DB: - case MATH_DB2LINEAR: - case LOGIC_NEAREST_PO2: - case OBJ_WEAKREF: - case TYPE_OF: - case TEXT_CHAR: - case TEXT_ORD: - case TEXT_STR: - case TEXT_PRINT: - case TEXT_PRINTERR: - case TEXT_PRINTRAW: - case VAR_TO_STR: - case STR_TO_VAR: - case TYPE_EXISTS: - return 1; - case VAR_TO_BYTES: - case BYTES_TO_VAR: - case MATH_ATAN2: - case MATH_FMOD: - case MATH_FPOSMOD: - case MATH_POSMOD: - case MATH_POW: - case MATH_EASE: - case MATH_STEPIFY: - case MATH_RANDOM: - case MATH_POLAR2CARTESIAN: - case MATH_CARTESIAN2POLAR: - case LOGIC_MAX: - case LOGIC_MIN: - case FUNC_FUNCREF: - case TYPE_CONVERT: - case COLORN: - return 2; - case MATH_LERP: - case MATH_LERP_ANGLE: - case MATH_INVERSE_LERP: - case MATH_SMOOTHSTEP: - case MATH_MOVE_TOWARD: - case MATH_DECTIME: - case MATH_WRAP: - case MATH_WRAPF: - case LOGIC_CLAMP: - return 3; - case MATH_RANGE_LERP: - return 5; - case FUNC_MAX: { - } - } - return 0; -} - -#define VALIDATE_ARG_NUM(m_arg) \ - if (!p_inputs[m_arg]->is_num()) { \ - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; \ - r_error.argument = m_arg; \ - r_error.expected = Variant::FLOAT; \ - return; \ - } - -void Expression::exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant *r_return, Callable::CallError &r_error, String &r_error_str) { - r_error.error = Callable::CallError::CALL_OK; - switch (p_func) { - case MATH_SIN: { - VALIDATE_ARG_NUM(0); - *r_return = Math::sin((double)*p_inputs[0]); - } break; - case MATH_COS: { - VALIDATE_ARG_NUM(0); - *r_return = Math::cos((double)*p_inputs[0]); - } break; - case MATH_TAN: { - VALIDATE_ARG_NUM(0); - *r_return = Math::tan((double)*p_inputs[0]); - } break; - case MATH_SINH: { - VALIDATE_ARG_NUM(0); - *r_return = Math::sinh((double)*p_inputs[0]); - } break; - case MATH_COSH: { - VALIDATE_ARG_NUM(0); - *r_return = Math::cosh((double)*p_inputs[0]); - } break; - case MATH_TANH: { - VALIDATE_ARG_NUM(0); - *r_return = Math::tanh((double)*p_inputs[0]); - } break; - case MATH_ASIN: { - VALIDATE_ARG_NUM(0); - *r_return = Math::asin((double)*p_inputs[0]); - } break; - case MATH_ACOS: { - VALIDATE_ARG_NUM(0); - *r_return = Math::acos((double)*p_inputs[0]); - } break; - case MATH_ATAN: { - VALIDATE_ARG_NUM(0); - *r_return = Math::atan((double)*p_inputs[0]); - } break; - case MATH_ATAN2: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *r_return = Math::atan2((double)*p_inputs[0], (double)*p_inputs[1]); - } break; - case MATH_SQRT: { - VALIDATE_ARG_NUM(0); - *r_return = Math::sqrt((double)*p_inputs[0]); - } break; - case MATH_FMOD: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *r_return = Math::fmod((double)*p_inputs[0], (double)*p_inputs[1]); - } break; - case MATH_FPOSMOD: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *r_return = Math::fposmod((double)*p_inputs[0], (double)*p_inputs[1]); - } break; - case MATH_POSMOD: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *r_return = Math::posmod((int)*p_inputs[0], (int)*p_inputs[1]); - } break; - case MATH_FLOOR: { - VALIDATE_ARG_NUM(0); - *r_return = Math::floor((double)*p_inputs[0]); - } break; - case MATH_CEIL: { - VALIDATE_ARG_NUM(0); - *r_return = Math::ceil((double)*p_inputs[0]); - } break; - case MATH_ROUND: { - VALIDATE_ARG_NUM(0); - *r_return = Math::round((double)*p_inputs[0]); - } break; - case MATH_ABS: { - if (p_inputs[0]->get_type() == Variant::INT) { - int64_t i = *p_inputs[0]; - *r_return = ABS(i); - } else if (p_inputs[0]->get_type() == Variant::FLOAT) { - real_t r = *p_inputs[0]; - *r_return = Math::abs(r); - } else { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::FLOAT; - } - } break; - case MATH_SIGN: { - if (p_inputs[0]->get_type() == Variant::INT) { - int64_t i = *p_inputs[0]; - *r_return = i < 0 ? -1 : (i > 0 ? +1 : 0); - } else if (p_inputs[0]->get_type() == Variant::FLOAT) { - real_t r = *p_inputs[0]; - *r_return = r < 0.0 ? -1.0 : (r > 0.0 ? +1.0 : 0.0); - } else { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::FLOAT; - } - } break; - case MATH_POW: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *r_return = Math::pow((double)*p_inputs[0], (double)*p_inputs[1]); - } break; - case MATH_LOG: { - VALIDATE_ARG_NUM(0); - *r_return = Math::log((double)*p_inputs[0]); - } break; - case MATH_EXP: { - VALIDATE_ARG_NUM(0); - *r_return = Math::exp((double)*p_inputs[0]); - } break; - case MATH_ISNAN: { - VALIDATE_ARG_NUM(0); - *r_return = Math::is_nan((double)*p_inputs[0]); - } break; - case MATH_ISINF: { - VALIDATE_ARG_NUM(0); - *r_return = Math::is_inf((double)*p_inputs[0]); - } break; - case MATH_EASE: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *r_return = Math::ease((double)*p_inputs[0], (double)*p_inputs[1]); - } break; - case MATH_STEP_DECIMALS: { - VALIDATE_ARG_NUM(0); - *r_return = Math::step_decimals((double)*p_inputs[0]); - } break; - case MATH_STEPIFY: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *r_return = Math::stepify((double)*p_inputs[0], (double)*p_inputs[1]); - } break; - case MATH_LERP: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); - *r_return = Math::lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); - } break; - case MATH_LERP_ANGLE: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); - *r_return = Math::lerp_angle((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); - } break; - case MATH_INVERSE_LERP: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); - *r_return = Math::inverse_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); - } break; - case MATH_RANGE_LERP: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); - VALIDATE_ARG_NUM(3); - VALIDATE_ARG_NUM(4); - *r_return = Math::range_lerp((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2], (double)*p_inputs[3], (double)*p_inputs[4]); - } break; - case MATH_SMOOTHSTEP: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); - *r_return = Math::smoothstep((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); - } break; - case MATH_MOVE_TOWARD: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); - *r_return = Math::move_toward((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); - } break; - case MATH_DECTIME: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); - *r_return = Math::dectime((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); - } break; - case MATH_RANDOMIZE: { - Math::randomize(); - - } break; - case MATH_RAND: { - *r_return = Math::rand(); - } break; - case MATH_RANDF: { - *r_return = Math::randf(); - } break; - case MATH_RANDOM: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - *r_return = Math::random((double)*p_inputs[0], (double)*p_inputs[1]); - } break; - case MATH_SEED: { - VALIDATE_ARG_NUM(0); - uint64_t seed = *p_inputs[0]; - Math::seed(seed); - - } break; - case MATH_RANDSEED: { - VALIDATE_ARG_NUM(0); - uint64_t seed = *p_inputs[0]; - int ret = Math::rand_from_seed(&seed); - Array reta; - reta.push_back(ret); - reta.push_back(seed); - *r_return = reta; - - } break; - case MATH_DEG2RAD: { - VALIDATE_ARG_NUM(0); - *r_return = Math::deg2rad((double)*p_inputs[0]); - } break; - case MATH_RAD2DEG: { - VALIDATE_ARG_NUM(0); - *r_return = Math::rad2deg((double)*p_inputs[0]); - } break; - case MATH_LINEAR2DB: { - VALIDATE_ARG_NUM(0); - *r_return = Math::linear2db((double)*p_inputs[0]); - } break; - case MATH_DB2LINEAR: { - VALIDATE_ARG_NUM(0); - *r_return = Math::db2linear((double)*p_inputs[0]); - } break; - case MATH_POLAR2CARTESIAN: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - double r = *p_inputs[0]; - double th = *p_inputs[1]; - *r_return = Vector2(r * Math::cos(th), r * Math::sin(th)); - } break; - case MATH_CARTESIAN2POLAR: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - double x = *p_inputs[0]; - double y = *p_inputs[1]; - *r_return = Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x)); - } break; - case MATH_WRAP: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); - *r_return = Math::wrapi((int64_t)*p_inputs[0], (int64_t)*p_inputs[1], (int64_t)*p_inputs[2]); - } break; - case MATH_WRAPF: { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); - *r_return = Math::wrapf((double)*p_inputs[0], (double)*p_inputs[1], (double)*p_inputs[2]); - } break; - case LOGIC_MAX: { - if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT) { - int64_t a = *p_inputs[0]; - int64_t b = *p_inputs[1]; - *r_return = MAX(a, b); - } else { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - - real_t a = *p_inputs[0]; - real_t b = *p_inputs[1]; - - *r_return = MAX(a, b); - } - - } break; - case LOGIC_MIN: { - if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT) { - int64_t a = *p_inputs[0]; - int64_t b = *p_inputs[1]; - *r_return = MIN(a, b); - } else { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - - real_t a = *p_inputs[0]; - real_t b = *p_inputs[1]; - - *r_return = MIN(a, b); - } - } break; - case LOGIC_CLAMP: { - if (p_inputs[0]->get_type() == Variant::INT && p_inputs[1]->get_type() == Variant::INT && p_inputs[2]->get_type() == Variant::INT) { - int64_t a = *p_inputs[0]; - int64_t b = *p_inputs[1]; - int64_t c = *p_inputs[2]; - *r_return = CLAMP(a, b, c); - } else { - VALIDATE_ARG_NUM(0); - VALIDATE_ARG_NUM(1); - VALIDATE_ARG_NUM(2); - - real_t a = *p_inputs[0]; - real_t b = *p_inputs[1]; - real_t c = *p_inputs[2]; - - *r_return = CLAMP(a, b, c); - } - } break; - case LOGIC_NEAREST_PO2: { - VALIDATE_ARG_NUM(0); - int64_t num = *p_inputs[0]; - *r_return = next_power_of_2(num); - } break; - case OBJ_WEAKREF: { - if (p_inputs[0]->get_type() != Variant::OBJECT) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::OBJECT; - - return; - } - - if (p_inputs[0]->is_ref()) { - REF r = *p_inputs[0]; - if (!r.is_valid()) { - return; - } - - Ref<WeakRef> wref = memnew(WeakRef); - wref->set_ref(r); - *r_return = wref; - } else { - Object *obj = *p_inputs[0]; - if (!obj) { - return; - } - Ref<WeakRef> wref = memnew(WeakRef); - wref->set_obj(obj); - *r_return = wref; - } - - } break; - case FUNC_FUNCREF: { - if (p_inputs[0]->get_type() != Variant::OBJECT) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::OBJECT; - - return; - } - if (p_inputs[1]->get_type() != Variant::STRING && p_inputs[1]->get_type() != Variant::NODE_PATH) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 1; - r_error.expected = Variant::STRING; - - return; - } - - Ref<FuncRef> fr = memnew(FuncRef); - - fr->set_instance(*p_inputs[0]); - fr->set_function(*p_inputs[1]); - - *r_return = fr; - - } break; - case TYPE_CONVERT: { - VALIDATE_ARG_NUM(1); - int type = *p_inputs[1]; - if (type < 0 || type >= Variant::VARIANT_MAX) { - r_error_str = RTR("Invalid type argument to convert(), use TYPE_* constants."); - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::INT; - return; - - } else { - *r_return = Variant::construct(Variant::Type(type), p_inputs, 1, r_error); - } - } break; - case TYPE_OF: { - *r_return = p_inputs[0]->get_type(); - - } break; - case TYPE_EXISTS: { - *r_return = ClassDB::class_exists(*p_inputs[0]); - - } break; - case TEXT_CHAR: { - char32_t result[2] = { *p_inputs[0], 0 }; - - *r_return = String(result); - - } break; - case TEXT_ORD: { - if (p_inputs[0]->get_type() != Variant::STRING) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::STRING; - - return; - } - - String str = *p_inputs[0]; - - if (str.length() != 1) { - r_error_str = RTR("Expected a string of length 1 (a character)."); - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::STRING; - - return; - } - - *r_return = str.get(0); - - } break; - case TEXT_STR: { - String str = *p_inputs[0]; - - *r_return = str; - - } break; - case TEXT_PRINT: { - String str = *p_inputs[0]; - print_line(str); - - } break; - - case TEXT_PRINTERR: { - String str = *p_inputs[0]; - print_error(str); - - } break; - case TEXT_PRINTRAW: { - String str = *p_inputs[0]; - OS::get_singleton()->print("%s", str.utf8().get_data()); - - } break; - case VAR_TO_STR: { - String vars; - VariantWriter::write_to_string(*p_inputs[0], vars); - *r_return = vars; - } break; - case STR_TO_VAR: { - if (p_inputs[0]->get_type() != Variant::STRING) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::STRING; - - return; - } - - VariantParser::StreamString ss; - ss.s = *p_inputs[0]; - - String errs; - int line; - Error err = VariantParser::parse(&ss, *r_return, errs, line); - - if (err != OK) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::STRING; - *r_return = "Parse error at line " + itos(line) + ": " + errs; - return; - } - - } break; - case VAR_TO_BYTES: { - PackedByteArray barr; - bool full_objects = *p_inputs[1]; - int len; - Error err = encode_variant(*p_inputs[0], nullptr, len, full_objects); - if (err) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::NIL; - r_error_str = "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID)."; - return; - } - - barr.resize(len); - { - uint8_t *w = barr.ptrw(); - encode_variant(*p_inputs[0], w, len, full_objects); - } - *r_return = barr; - } break; - case BYTES_TO_VAR: { - if (p_inputs[0]->get_type() != Variant::PACKED_BYTE_ARRAY) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::PACKED_BYTE_ARRAY; - - return; - } - - PackedByteArray varr = *p_inputs[0]; - bool allow_objects = *p_inputs[1]; - Variant ret; - { - const uint8_t *r = varr.ptr(); - Error err = decode_variant(ret, r, varr.size(), nullptr, allow_objects); - if (err != OK) { - r_error_str = RTR("Not enough bytes for decoding bytes, or invalid format."); - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::PACKED_BYTE_ARRAY; - return; - } - } - - *r_return = ret; - - } break; - case COLORN: { - VALIDATE_ARG_NUM(1); - - Color color = Color::named(*p_inputs[0]); - color.a = *p_inputs[1]; - - *r_return = String(color); - - } break; - default: { - } - } -} - -//////// +#include "core/variant/variant_parser.h" static bool _is_number(char32_t c) { return (c >= '0' && c <= '9'); @@ -1112,18 +410,9 @@ Error Expression::_get_token(Token &r_token) { } else if (id == "self") { r_token.type = TK_SELF; } else { - for (int i = 0; i < Variant::VARIANT_MAX; i++) { - if (id == Variant::get_type_name(Variant::Type(i))) { - r_token.type = TK_BASIC_TYPE; - r_token.value = i; - return OK; - } - } - - BuiltinFunc bifunc = find_function(id); - if (bifunc != FUNC_MAX) { + if (Variant::has_utility_function(id)) { r_token.type = TK_BUILTIN_FUNC; - r_token.value = bifunc; + r_token.value = id; return OK; } @@ -1421,6 +710,8 @@ Expression::ENode *Expression::_parse_expression() { case TK_BUILTIN_FUNC: { //builtin function + StringName func = tk.value; + _get_token(tk); if (tk.type != TK_PARENTHESIS_OPEN) { _set_error("Expected '('"); @@ -1428,7 +719,7 @@ Expression::ENode *Expression::_parse_expression() { } BuiltinFuncNode *bifunc = alloc_node<BuiltinFuncNode>(); - bifunc->func = BuiltinFunc(int(tk.value)); + bifunc->func = func; while (true) { int cofs = str_ofs; @@ -1456,9 +747,11 @@ Expression::ENode *Expression::_parse_expression() { } } - int expected_args = get_func_argument_count(bifunc->func); - if (bifunc->arguments.size() != expected_args) { - _set_error("Builtin func '" + get_func_name(bifunc->func) + "' expects " + itos(expected_args) + " arguments."); + if (!Variant::is_utility_function_vararg(bifunc->func)) { + int expected_args = Variant::get_utility_function_argument_count(bifunc->func); + if (expected_args != bifunc->arguments.size()) { + _set_error("Builtin func '" + String(bifunc->func) + "' expects " + itos(expected_args) + " arguments."); + } } expr = bifunc; @@ -1710,31 +1003,19 @@ Expression::ENode *Expression::_parse_expression() { priority = 1; unary = true; break; - case Variant::OP_MULTIPLY: - priority = 2; - break; case Variant::OP_DIVIDE: - priority = 2; - break; case Variant::OP_MODULE: priority = 2; break; - case Variant::OP_ADD: - priority = 3; - break; case Variant::OP_SUBTRACT: priority = 3; break; - case Variant::OP_SHIFT_LEFT: - priority = 4; - break; case Variant::OP_SHIFT_RIGHT: priority = 4; break; - case Variant::OP_BIT_AND: priority = 5; break; @@ -1744,31 +1025,17 @@ Expression::ENode *Expression::_parse_expression() { case Variant::OP_BIT_OR: priority = 7; break; - case Variant::OP_LESS: - priority = 8; - break; case Variant::OP_LESS_EQUAL: - priority = 8; - break; case Variant::OP_GREATER: - priority = 8; - break; case Variant::OP_GREATER_EQUAL: - priority = 8; - break; - case Variant::OP_EQUAL: - priority = 8; - break; case Variant::OP_NOT_EQUAL: priority = 8; break; - case Variant::OP_IN: priority = 10; break; - case Variant::OP_NOT: priority = 11; unary = true; @@ -1779,7 +1046,6 @@ Expression::ENode *Expression::_parse_expression() { case Variant::OP_OR: priority = 13; break; - default: { _set_error("Parser bug, invalid operator in expression: " + itos(expression[i].op)); return nullptr; @@ -1973,7 +1239,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: } bool valid; - r_ret = base.get_named(index->name, &valid); + r_ret = base.get_named(index->name, valid); if (!valid) { r_error_str = vformat(RTR("Invalid named index '%s' for base type %s"), String(index->name), Variant::get_type_name(base.get_type())); return true; @@ -2041,7 +1307,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: } Callable::CallError ce; - r_ret = Variant::construct(constructor->data_type, (const Variant **)argp.ptr(), argp.size(), ce); + Variant::construct(constructor->data_type, r_ret, (const Variant **)argp.ptr(), argp.size(), ce); if (ce.error != Callable::CallError::CALL_OK) { r_error_str = vformat(RTR("Invalid arguments to construct '%s'"), Variant::get_type_name(constructor->data_type)); @@ -2067,11 +1333,11 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: argp.write[i] = &arr[i]; } + r_ret = Variant(); //may not return anything Callable::CallError ce; - exec_func(bifunc->func, (const Variant **)argp.ptr(), &r_ret, ce, r_error_str); - + Variant::call_utility_function(bifunc->func, &r_ret, (const Variant **)argp.ptr(), argp.size(), ce); if (ce.error != Callable::CallError::CALL_OK) { - r_error_str = "Builtin Call Failed. " + r_error_str; + r_error_str = "Builtin Call Failed. " + Variant::get_call_error_text(bifunc->func, (const Variant **)argp.ptr(), argp.size(), ce); return true; } @@ -2103,7 +1369,7 @@ bool Expression::_execute(const Array &p_inputs, Object *p_instance, Expression: } Callable::CallError ce; - r_ret = base.call(call->method, (const Variant **)argp.ptr(), argp.size(), ce); + base.call(call->method, (const Variant **)argp.ptr(), argp.size(), r_ret, ce); if (ce.error != Callable::CallError::CALL_OK) { r_error_str = vformat(RTR("On call to '%s':"), String(call->method)); diff --git a/core/math/expression.h b/core/math/expression.h index f2cfe6b1a6..a6b288ed6e 100644 --- a/core/math/expression.h +++ b/core/math/expression.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,92 +31,12 @@ #ifndef EXPRESSION_H #define EXPRESSION_H -#include "core/reference.h" +#include "core/object/reference.h" class Expression : public Reference { GDCLASS(Expression, Reference); -public: - enum BuiltinFunc { - MATH_SIN, - MATH_COS, - MATH_TAN, - MATH_SINH, - MATH_COSH, - MATH_TANH, - MATH_ASIN, - MATH_ACOS, - MATH_ATAN, - MATH_ATAN2, - MATH_SQRT, - MATH_FMOD, - MATH_FPOSMOD, - MATH_POSMOD, - MATH_FLOOR, - MATH_CEIL, - MATH_ROUND, - MATH_ABS, - MATH_SIGN, - MATH_POW, - MATH_LOG, - MATH_EXP, - MATH_ISNAN, - MATH_ISINF, - MATH_EASE, - MATH_STEP_DECIMALS, - MATH_STEPIFY, - MATH_LERP, - MATH_LERP_ANGLE, - MATH_INVERSE_LERP, - MATH_RANGE_LERP, - MATH_SMOOTHSTEP, - MATH_MOVE_TOWARD, - MATH_DECTIME, - MATH_RANDOMIZE, - MATH_RAND, - MATH_RANDF, - MATH_RANDOM, - MATH_SEED, - MATH_RANDSEED, - MATH_DEG2RAD, - MATH_RAD2DEG, - MATH_LINEAR2DB, - MATH_DB2LINEAR, - MATH_POLAR2CARTESIAN, - MATH_CARTESIAN2POLAR, - MATH_WRAP, - MATH_WRAPF, - LOGIC_MAX, - LOGIC_MIN, - LOGIC_CLAMP, - LOGIC_NEAREST_PO2, - OBJ_WEAKREF, - FUNC_FUNCREF, - TYPE_CONVERT, - TYPE_OF, - TYPE_EXISTS, - TEXT_CHAR, - TEXT_ORD, - TEXT_STR, - TEXT_PRINT, - TEXT_PRINTERR, - TEXT_PRINTRAW, - VAR_TO_STR, - STR_TO_VAR, - VAR_TO_BYTES, - BYTES_TO_VAR, - COLORN, - FUNC_MAX - }; - - static int get_func_argument_count(BuiltinFunc p_func); - static String get_func_name(BuiltinFunc p_func); - static void exec_func(BuiltinFunc p_func, const Variant **p_inputs, Variant *r_return, Callable::CallError &r_error, String &r_error_str); - static BuiltinFunc find_function(const String &p_string); - private: - static const char *func_name[FUNC_MAX]; - struct Input { Variant::Type type = Variant::NIL; String name; @@ -213,7 +133,7 @@ private: ENode *next = nullptr; - Type type; + Type type = TYPE_INPUT; ENode() {} virtual ~ENode() { @@ -224,7 +144,7 @@ private: }; struct ExpressionNode { - bool is_op; + bool is_op = false; union { Variant::Operator op; ENode *node; @@ -234,23 +154,23 @@ private: ENode *_parse_expression(); struct InputNode : public ENode { - int index; + int index = 0; InputNode() { type = TYPE_INPUT; } }; struct ConstantNode : public ENode { - Variant value; + Variant value = Variant::NIL; ConstantNode() { type = TYPE_CONSTANT; } }; struct OperatorNode : public ENode { - Variant::Operator op; + Variant::Operator op = Variant::Operator::OP_ADD; - ENode *nodes[2]; + ENode *nodes[2] = { nullptr, nullptr }; OperatorNode() { type = TYPE_OPERATOR; @@ -264,8 +184,8 @@ private: }; struct IndexNode : public ENode { - ENode *base; - ENode *index; + ENode *base = nullptr; + ENode *index = nullptr; IndexNode() { type = TYPE_INDEX; @@ -273,7 +193,7 @@ private: }; struct NamedIndexNode : public ENode { - ENode *base; + ENode *base = nullptr; StringName name; NamedIndexNode() { @@ -282,7 +202,7 @@ private: }; struct ConstructorNode : public ENode { - Variant::Type data_type; + Variant::Type data_type = Variant::Type::NIL; Vector<ENode *> arguments; ConstructorNode() { @@ -291,7 +211,7 @@ private: }; struct CallNode : public ENode { - ENode *base; + ENode *base = nullptr; StringName method; Vector<ENode *> arguments; @@ -315,7 +235,7 @@ private: }; struct BuiltinFuncNode : public ENode { - BuiltinFunc func; + StringName func; Vector<ENode *> arguments; BuiltinFuncNode() { type = TYPE_BUILTIN_FUNC; diff --git a/core/math/face3.cpp b/core/math/face3.cpp index db2bfaa58b..beb0a8e405 100644 --- a/core/math/face3.cpp +++ b/core/math/face3.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/face3.h b/core/math/face3.h index fb40e8ab9e..2e86b0a904 100644 --- a/core/math/face3.h +++ b/core/math/face3.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/geometry_2d.cpp b/core/math/geometry_2d.cpp index 4636e1c774..5d4c31088b 100644 --- a/core/math/geometry_2d.cpp +++ b/core/math/geometry_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/geometry_2d.h b/core/math/geometry_2d.h index cfd7abfacb..4b5aef352f 100644 --- a/core/math/geometry_2d.h +++ b/core/math/geometry_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,8 +34,8 @@ #include "core/math/delaunay_2d.h" #include "core/math/rect2.h" #include "core/math/triangulate.h" -#include "core/object.h" -#include "core/vector.h" +#include "core/object/object.h" +#include "core/templates/vector.h" class Geometry2D { Geometry2D(); @@ -145,6 +145,12 @@ public: return p_segment[0] + n * d; // Inside. } +// Disable False Positives in MSVC compiler; we correctly check for 0 here to prevent a division by 0. +// See: https://github.com/godotengine/godot/pull/44274 +#ifdef _MSC_VER +#pragma warning(disable : 4723) +#endif + static bool line_intersects_line(const Vector2 &p_from_a, const Vector2 &p_dir_a, const Vector2 &p_from_b, const Vector2 &p_dir_b, Vector2 &r_result) { // See http://paulbourke.net/geometry/pointlineplane/ @@ -159,6 +165,11 @@ public: return true; } +// Re-enable division by 0 warning +#ifdef _MSC_VER +#pragma warning(default : 4723) +#endif + static bool segment_intersects_segment(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b, Vector2 *r_result) { Vector2 B = p_to_a - p_from_a; Vector2 C = p_from_b - p_from_a; diff --git a/core/math/geometry_3d.cpp b/core/math/geometry_3d.cpp index 2c19fe2085..a918d1de0d 100644 --- a/core/math/geometry_3d.cpp +++ b/core/math/geometry_3d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "geometry_3d.h" -#include "core/print_string.h" +#include "core/string/print_string.h" #include "thirdparty/misc/clipper.hpp" #include "thirdparty/misc/triangulator.h" @@ -241,7 +241,6 @@ Vector<Vector<Face3>> Geometry3D::separate_objects(Vector<Face3> p_array) { /*** GEOMETRY WRAPPER ***/ enum _CellFlags { - _CELL_SOLID = 1, _CELL_EXTERIOR = 2, _CELL_STEP_MASK = 0x1C, @@ -262,7 +261,6 @@ enum _CellFlags { _CELL_PREV_Z_POS = 5 << 5, _CELL_PREV_Z_NEG = 6 << 5, _CELL_PREV_FIRST = 7 << 5, - }; static inline void _plot_face(uint8_t ***p_cell_status, int x, int y, int z, int len_x, int len_y, int len_z, const Vector3 &voxelsize, const Face3 &p_face) { diff --git a/core/math/geometry_3d.h b/core/math/geometry_3d.h index 11cac8f108..825817af5e 100644 --- a/core/math/geometry_3d.h +++ b/core/math/geometry_3d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,8 +32,8 @@ #define GEOMETRY_3D_H #include "core/math/face3.h" -#include "core/object.h" -#include "core/vector.h" +#include "core/object/object.h" +#include "core/templates/vector.h" class Geometry3D { Geometry3D(); diff --git a/core/math/math_defs.h b/core/math/math_defs.h index 4928c96abd..df2223fb78 100644 --- a/core/math/math_defs.h +++ b/core/math/math_defs.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -66,35 +66,31 @@ enum ClockDirection { }; enum Orientation { - HORIZONTAL, VERTICAL }; enum HAlign { - HALIGN_LEFT, HALIGN_CENTER, - HALIGN_RIGHT + HALIGN_RIGHT, + HALIGN_FILL, }; enum VAlign { - VALIGN_TOP, VALIGN_CENTER, VALIGN_BOTTOM }; -enum Margin { - - MARGIN_LEFT, - MARGIN_TOP, - MARGIN_RIGHT, - MARGIN_BOTTOM +enum Side { + SIDE_LEFT, + SIDE_TOP, + SIDE_RIGHT, + SIDE_BOTTOM }; enum Corner { - CORNER_TOP_LEFT, CORNER_TOP_RIGHT, CORNER_BOTTOM_RIGHT, diff --git a/core/math/math_fieldwise.cpp b/core/math/math_fieldwise.cpp index ef2a0c5339..0985a727f2 100644 --- a/core/math/math_fieldwise.cpp +++ b/core/math/math_fieldwise.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,9 +47,7 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const /* clang-format off */ switch (p_source.get_type()) { - case Variant::VECTOR2: { - SETUP_TYPE(Vector2) /**/ TRY_TRANSFER_FIELD("x", x) @@ -59,7 +57,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const } case Variant::RECT2: { - SETUP_TYPE(Rect2) /**/ TRY_TRANSFER_FIELD("x", position.x) @@ -71,7 +68,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const } case Variant::VECTOR3: { - SETUP_TYPE(Vector3) /**/ TRY_TRANSFER_FIELD("x", x) @@ -82,7 +78,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const } case Variant::PLANE: { - SETUP_TYPE(Plane) /**/ TRY_TRANSFER_FIELD("x", normal.x) @@ -94,7 +89,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const } case Variant::QUAT: { - SETUP_TYPE(Quat) /**/ TRY_TRANSFER_FIELD("x", x) @@ -106,7 +100,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const } case Variant::AABB: { - SETUP_TYPE(AABB) /**/ TRY_TRANSFER_FIELD("px", position.x) @@ -120,7 +113,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const } case Variant::TRANSFORM2D: { - SETUP_TYPE(Transform2D) /**/ TRY_TRANSFER_FIELD("xx", elements[0][0]) @@ -134,7 +126,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const } case Variant::BASIS: { - SETUP_TYPE(Basis) /**/ TRY_TRANSFER_FIELD("xx", elements[0][0]) @@ -151,7 +142,6 @@ Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const } case Variant::TRANSFORM: { - SETUP_TYPE(Transform) /**/ TRY_TRANSFER_FIELD("xx", basis.elements[0][0]) diff --git a/core/math/math_fieldwise.h b/core/math/math_fieldwise.h index c1ee9ec8f0..fe44d09900 100644 --- a/core/math/math_fieldwise.h +++ b/core/math/math_fieldwise.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +33,7 @@ #ifdef TOOLS_ENABLED -#include "core/variant.h" +#include "core/variant/variant.h" Variant fieldwise_assign(const Variant &p_target, const Variant &p_source, const String &p_field); diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index 1585c96b38..e92bb9f4aa 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,12 +30,10 @@ #include "math_funcs.h" -#include "core/error_macros.h" +#include "core/error/error_macros.h" RandomPCG Math::default_rand(RandomPCG::DEFAULT_SEED, RandomPCG::DEFAULT_INC); -#define PHI 0x9e3779b9 - uint32_t Math::rand_from_seed(uint64_t *seed) { RandomPCG rng = RandomPCG(*seed, RandomPCG::DEFAULT_INC); uint32_t r = rng.rand(); @@ -125,7 +123,7 @@ double Math::ease(double p_x, double p_c) { } } -double Math::stepify(double p_value, double p_step) { +double Math::snapped(double p_value, double p_step) { if (p_step != 0) { p_value = Math::floor(p_value / p_step + 0.5) * p_step; } @@ -183,3 +181,7 @@ double Math::random(double from, double to) { float Math::random(float from, float to) { return default_rand.random(from, to); } + +int Math::random(int from, int to) { + return default_rand.random(from, to); +} diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index f83ee44f4a..c7d24e9c58 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -198,6 +198,23 @@ public: value += 0.0; return value; } + static _ALWAYS_INLINE_ float fposmodp(float p_x, float p_y) { + float value = Math::fmod(p_x, p_y); + if (value < 0) { + value += p_y; + } + value += 0.0; + return value; + } + static _ALWAYS_INLINE_ double fposmodp(double p_x, double p_y) { + double value = Math::fmod(p_x, p_y); + if (value < 0) { + value += p_y; + } + value += 0.0; + return value; + } + static _ALWAYS_INLINE_ int posmod(int p_x, int p_y) { int value = p_x % p_y; if ((value < 0 && p_y > 0) || (value > 0 && p_y < 0)) { @@ -275,7 +292,7 @@ public: static double ease(double p_x, double p_c); static int step_decimals(double p_step); static int range_step_decimals(double p_step); - static double stepify(double p_value, double p_step); + static double snapped(double p_value, double p_step); static double dectime(double p_value, double p_amount, double p_step); static uint32_t larger_prime(uint32_t p_val); @@ -289,7 +306,7 @@ public: static double random(double from, double to); static float random(float from, float to); - static real_t random(int from, int to) { return (real_t)random((real_t)from, (real_t)to); } + static int random(int from, int to); static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b) { // Check for exact equality first, required to handle "infinity" values. @@ -455,12 +472,12 @@ public: } static _ALWAYS_INLINE_ float snap_scalar(float p_offset, float p_step, float p_target) { - return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target; + return p_step != 0 ? Math::snapped(p_target - p_offset, p_step) + p_offset : p_target; } static _ALWAYS_INLINE_ float snap_scalar_separation(float p_offset, float p_step, float p_target, float p_separation) { if (p_step != 0) { - float a = Math::stepify(p_target - p_offset, p_step + p_separation) + p_offset; + float a = Math::snapped(p_target - p_offset, p_step + p_separation) + p_offset; float b = a; if (p_target >= 0) { b -= p_separation; diff --git a/core/math/octree.h b/core/math/octree.h index 5d9688d442..493a63aa2e 100644 --- a/core/math/octree.h +++ b/core/math/octree.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,13 +31,13 @@ #ifndef OCTREE_H #define OCTREE_H -#include "core/list.h" -#include "core/map.h" #include "core/math/aabb.h" #include "core/math/geometry_3d.h" #include "core/math/vector3.h" -#include "core/print_string.h" -#include "core/variant.h" +#include "core/string/print_string.h" +#include "core/templates/list.h" +#include "core/templates/map.h" +#include "core/variant/variant.h" typedef uint32_t OctreeElementID; @@ -379,7 +379,6 @@ void Octree<T, use_pairs, AL>::_insert_element(Element *p_element, Octant *p_oct if (p_octant->aabb.size.x / OCTREE_DIVISOR < element_size) { //if (p_octant->aabb.size.x*0.5 < element_size) { - /* at smallest possible size for the element */ typename Element::OctantOwner owner; owner.octant = p_octant; @@ -573,7 +572,7 @@ bool Octree<T, use_pairs, AL>::_remove_element_from_octant(Element *p_element, O Octant *parent = p_octant->parent; - if (p_octant->children_count == 0 && p_octant->elements.empty() && p_octant->pairable_elements.empty()) { + if (p_octant->children_count == 0 && p_octant->elements.is_empty() && p_octant->pairable_elements.is_empty()) { // erase octant if (p_octant == root) { // won't have a parent, just erase @@ -943,7 +942,7 @@ void Octree<T, use_pairs, AL>::_cull_convex(Octant *p_octant, _CullConvexData *p return; //pointless } - if (!p_octant->elements.empty()) { + if (!p_octant->elements.is_empty()) { typename List<Element *, AL>::Element *I; I = p_octant->elements.front(); @@ -966,7 +965,7 @@ void Octree<T, use_pairs, AL>::_cull_convex(Octant *p_octant, _CullConvexData *p } } - if (use_pairs && !p_octant->pairable_elements.empty()) { + if (use_pairs && !p_octant->pairable_elements.is_empty()) { typename List<Element *, AL>::Element *I; I = p_octant->pairable_elements.front(); @@ -1002,7 +1001,7 @@ void Octree<T, use_pairs, AL>::_cull_aabb(Octant *p_octant, const AABB &p_aabb, return; //pointless } - if (!p_octant->elements.empty()) { + if (!p_octant->elements.is_empty()) { typename List<Element *, AL>::Element *I; I = p_octant->elements.front(); for (; I; I = I->next()) { @@ -1028,7 +1027,7 @@ void Octree<T, use_pairs, AL>::_cull_aabb(Octant *p_octant, const AABB &p_aabb, } } - if (use_pairs && !p_octant->pairable_elements.empty()) { + if (use_pairs && !p_octant->pairable_elements.is_empty()) { typename List<Element *, AL>::Element *I; I = p_octant->pairable_elements.front(); for (; I; I = I->next()) { @@ -1066,7 +1065,7 @@ void Octree<T, use_pairs, AL>::_cull_segment(Octant *p_octant, const Vector3 &p_ return; //pointless } - if (!p_octant->elements.empty()) { + if (!p_octant->elements.is_empty()) { typename List<Element *, AL>::Element *I; I = p_octant->elements.front(); for (; I; I = I->next()) { @@ -1092,7 +1091,7 @@ void Octree<T, use_pairs, AL>::_cull_segment(Octant *p_octant, const Vector3 &p_ } } - if (use_pairs && !p_octant->pairable_elements.empty()) { + if (use_pairs && !p_octant->pairable_elements.is_empty()) { typename List<Element *, AL>::Element *I; I = p_octant->pairable_elements.front(); for (; I; I = I->next()) { @@ -1133,7 +1132,7 @@ void Octree<T, use_pairs, AL>::_cull_point(Octant *p_octant, const Vector3 &p_po return; //pointless } - if (!p_octant->elements.empty()) { + if (!p_octant->elements.is_empty()) { typename List<Element *, AL>::Element *I; I = p_octant->elements.front(); for (; I; I = I->next()) { @@ -1159,7 +1158,7 @@ void Octree<T, use_pairs, AL>::_cull_point(Octant *p_octant, const Vector3 &p_po } } - if (use_pairs && !p_octant->pairable_elements.empty()) { + if (use_pairs && !p_octant->pairable_elements.is_empty()) { typename List<Element *, AL>::Element *I; I = p_octant->pairable_elements.front(); for (; I; I = I->next()) { diff --git a/core/math/plane.cpp b/core/math/plane.cpp index 4200484c59..f1d3bbbd54 100644 --- a/core/math/plane.cpp +++ b/core/math/plane.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,6 +31,7 @@ #include "plane.h" #include "core/math/math_funcs.h" +#include "core/variant/variant.h" void Plane::set_normal(const Vector3 &p_normal) { normal = p_normal; @@ -138,6 +139,31 @@ bool Plane::intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vec return true; } +Variant Plane::intersect_3_bind(const Plane &p_plane1, const Plane &p_plane2) const { + Vector3 inters; + if (intersect_3(p_plane1, p_plane2, &inters)) { + return inters; + } else { + return Variant(); + } +} +Variant Plane::intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const { + Vector3 inters; + if (intersects_ray(p_from, p_dir, &inters)) { + return inters; + } else { + return Variant(); + } +} +Variant Plane::intersects_segment_bind(const Vector3 &p_begin, const Vector3 &p_end) const { + Vector3 inters; + if (intersects_segment(p_begin, p_end, &inters)) { + return inters; + } else { + return Variant(); + } +} + /* misc */ bool Plane::is_equal_approx_any_side(const Plane &p_plane) const { diff --git a/core/math/plane.h b/core/math/plane.h index 70a6111edd..2267b28c53 100644 --- a/core/math/plane.h +++ b/core/math/plane.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,6 +33,8 @@ #include "core/math/vector3.h" +class Variant; + class Plane { public: Vector3 normal; @@ -59,6 +61,11 @@ public: bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *p_intersection) const; bool intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 *p_intersection) const; + // For Variant bindings. + Variant intersect_3_bind(const Plane &p_plane1, const Plane &p_plane2) const; + Variant intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const; + Variant intersects_segment_bind(const Vector3 &p_begin, const Vector3 &p_end) const; + _FORCE_INLINE_ Vector3 project(const Vector3 &p_point) const { return p_point - normal * distance_to(p_point); } diff --git a/core/math/quat.cpp b/core/math/quat.cpp index c10f5da494..4cecc20fef 100644 --- a/core/math/quat.cpp +++ b/core/math/quat.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #include "quat.h" #include "core/math/basis.h" -#include "core/print_string.h" +#include "core/string/print_string.h" // set_euler_xyz expects a vector containing the Euler angles in the format // (ax,ay,az), where ax is the angle of rotation around x axis, @@ -106,16 +106,16 @@ Vector3 Quat::get_euler_yxz() const { return m.get_euler_yxz(); } -void Quat::operator*=(const Quat &q) { - set(w * q.x + x * q.w + y * q.z - z * q.y, - w * q.y + y * q.w + z * q.x - x * q.z, - w * q.z + z * q.w + x * q.y - y * q.x, - w * q.w - x * q.x - y * q.y - z * q.z); +void Quat::operator*=(const Quat &p_q) { + set(w * p_q.x + x * p_q.w + y * p_q.z - z * p_q.y, + w * p_q.y + y * p_q.w + z * p_q.x - x * p_q.z, + w * p_q.z + z * p_q.w + x * p_q.y - y * p_q.x, + w * p_q.w - x * p_q.x - y * p_q.y - z * p_q.z); } -Quat Quat::operator*(const Quat &q) const { +Quat Quat::operator*(const Quat &p_q) const { Quat r = *this; - r *= q; + r *= p_q; return r; } @@ -146,29 +146,29 @@ Quat Quat::inverse() const { return Quat(-x, -y, -z, w); } -Quat Quat::slerp(const Quat &q, const real_t &t) const { +Quat Quat::slerp(const Quat &p_to, const real_t &p_weight) const { #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(!is_normalized(), Quat(), "The start quaternion must be normalized."); - ERR_FAIL_COND_V_MSG(!q.is_normalized(), Quat(), "The end quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quat(), "The end quaternion must be normalized."); #endif Quat to1; real_t omega, cosom, sinom, scale0, scale1; // calc cosine - cosom = dot(q); + cosom = dot(p_to); // adjust signs (if necessary) if (cosom < 0.0) { cosom = -cosom; - to1.x = -q.x; - to1.y = -q.y; - to1.z = -q.z; - to1.w = -q.w; + to1.x = -p_to.x; + to1.y = -p_to.y; + to1.z = -p_to.z; + to1.w = -p_to.w; } else { - to1.x = q.x; - to1.y = q.y; - to1.z = q.z; - to1.w = q.w; + to1.x = p_to.x; + to1.y = p_to.y; + to1.z = p_to.z; + to1.w = p_to.w; } // calculate coefficients @@ -177,13 +177,13 @@ Quat Quat::slerp(const Quat &q, const real_t &t) const { // standard case (slerp) omega = Math::acos(cosom); sinom = Math::sin(omega); - scale0 = Math::sin((1.0 - t) * omega) / sinom; - scale1 = Math::sin(t * omega) / sinom; + scale0 = Math::sin((1.0 - p_weight) * omega) / sinom; + scale1 = Math::sin(p_weight * omega) / sinom; } else { // "from" and "to" quaternions are very close // ... so we can do a linear interpolation - scale0 = 1.0 - t; - scale1 = t; + scale0 = 1.0 - p_weight; + scale1 = p_weight; } // calculate final values return Quat( @@ -193,14 +193,14 @@ Quat Quat::slerp(const Quat &q, const real_t &t) const { scale0 * w + scale1 * to1.w); } -Quat Quat::slerpni(const Quat &q, const real_t &t) const { +Quat Quat::slerpni(const Quat &p_to, const real_t &p_weight) const { #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(!is_normalized(), Quat(), "The start quaternion must be normalized."); - ERR_FAIL_COND_V_MSG(!q.is_normalized(), Quat(), "The end quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quat(), "The end quaternion must be normalized."); #endif const Quat &from = *this; - real_t dot = from.dot(q); + real_t dot = from.dot(p_to); if (Math::absf(dot) > 0.9999) { return from; @@ -208,24 +208,24 @@ Quat Quat::slerpni(const Quat &q, const real_t &t) const { real_t theta = Math::acos(dot), sinT = 1.0 / Math::sin(theta), - newFactor = Math::sin(t * theta) * sinT, - invFactor = Math::sin((1.0 - t) * theta) * sinT; + newFactor = Math::sin(p_weight * theta) * sinT, + invFactor = Math::sin((1.0 - p_weight) * theta) * sinT; - return Quat(invFactor * from.x + newFactor * q.x, - invFactor * from.y + newFactor * q.y, - invFactor * from.z + newFactor * q.z, - invFactor * from.w + newFactor * q.w); + return Quat(invFactor * from.x + newFactor * p_to.x, + invFactor * from.y + newFactor * p_to.y, + invFactor * from.z + newFactor * p_to.z, + invFactor * from.w + newFactor * p_to.w); } -Quat Quat::cubic_slerp(const Quat &q, const Quat &prep, const Quat &postq, const real_t &t) const { +Quat Quat::cubic_slerp(const Quat &p_b, const Quat &p_pre_a, const Quat &p_post_b, const real_t &p_weight) const { #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(!is_normalized(), Quat(), "The start quaternion must be normalized."); - ERR_FAIL_COND_V_MSG(!q.is_normalized(), Quat(), "The end quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quat(), "The end quaternion must be normalized."); #endif //the only way to do slerp :| - real_t t2 = (1.0 - t) * t * 2; - Quat sp = this->slerp(q, t); - Quat sq = prep.slerpni(postq, t); + real_t t2 = (1.0 - p_weight) * p_weight * 2; + Quat sp = this->slerp(p_b, p_weight); + Quat sq = p_pre_a.slerpni(p_post_b, p_weight); return sp.slerpni(sq, t2); } diff --git a/core/math/quat.h b/core/math/quat.h index 3152b7d233..423a7f8dfe 100644 --- a/core/math/quat.h +++ b/core/math/quat.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,12 +36,26 @@ #include "core/math/math_defs.h" #include "core/math/math_funcs.h" -#include "core/ustring.h" +#include "core/string/ustring.h" class Quat { public: - real_t x = 0, y = 0, z = 0, w = 1; - + union { + struct { + real_t x; + real_t y; + real_t z; + real_t w; + }; + real_t components[4] = { 0, 0, 0, 1.0 }; + }; + + _FORCE_INLINE_ real_t &operator[](int idx) { + return components[idx]; + } + _FORCE_INLINE_ const real_t &operator[](int idx) const { + return components[idx]; + } _FORCE_INLINE_ real_t length_squared() const; bool is_equal_approx(const Quat &p_quat) const; real_t length() const; @@ -49,7 +63,7 @@ public: Quat normalized() const; bool is_normalized() const; Quat inverse() const; - _FORCE_INLINE_ real_t dot(const Quat &q) const; + _FORCE_INLINE_ real_t dot(const Quat &p_q) const; void set_euler_xyz(const Vector3 &p_euler); Vector3 get_euler_xyz() const; @@ -59,9 +73,9 @@ public: void set_euler(const Vector3 &p_euler) { set_euler_yxz(p_euler); }; Vector3 get_euler() const { return get_euler_yxz(); }; - Quat slerp(const Quat &q, const real_t &t) const; - Quat slerpni(const Quat &q, const real_t &t) const; - Quat cubic_slerp(const Quat &q, const Quat &prep, const Quat &postq, const real_t &t) const; + Quat slerp(const Quat &p_to, const real_t &p_weight) const; + Quat slerpni(const Quat &p_to, const real_t &p_weight) const; + Quat cubic_slerp(const Quat &p_b, const Quat &p_pre_a, const Quat &p_post_b, const real_t &p_weight) const; void set_axis_angle(const Vector3 &axis, const real_t &angle); _FORCE_INLINE_ void get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { @@ -72,8 +86,8 @@ public: r_axis.z = z * r; } - void operator*=(const Quat &q); - Quat operator*(const Quat &q) const; + void operator*=(const Quat &p_q); + Quat operator*(const Quat &p_q) const; Quat operator*(const Vector3 &v) const { return Quat(w * v.x + y * v.z - z * v.y, @@ -91,8 +105,12 @@ public: return v + ((uv * w) + u.cross(uv)) * ((real_t)2); } - _FORCE_INLINE_ void operator+=(const Quat &q); - _FORCE_INLINE_ void operator-=(const Quat &q); + _FORCE_INLINE_ Vector3 xform_inv(const Vector3 &v) const { + return inverse().xform(v); + } + + _FORCE_INLINE_ void operator+=(const Quat &p_q); + _FORCE_INLINE_ void operator-=(const Quat &p_q); _FORCE_INLINE_ void operator*=(const real_t &s); _FORCE_INLINE_ void operator/=(const real_t &s); _FORCE_INLINE_ Quat operator+(const Quat &q2) const; @@ -123,18 +141,18 @@ public: Quat(const Vector3 &axis, const real_t &angle) { set_axis_angle(axis, angle); } Quat(const Vector3 &euler) { set_euler(euler); } - Quat(const Quat &q) : - x(q.x), - y(q.y), - z(q.z), - w(q.w) { + Quat(const Quat &p_q) : + x(p_q.x), + y(p_q.y), + z(p_q.z), + w(p_q.w) { } - Quat &operator=(const Quat &q) { - x = q.x; - y = q.y; - z = q.z; - w = q.w; + Quat &operator=(const Quat &p_q) { + x = p_q.x; + y = p_q.y; + z = p_q.z; + w = p_q.w; return *this; } @@ -160,26 +178,26 @@ public: } }; -real_t Quat::dot(const Quat &q) const { - return x * q.x + y * q.y + z * q.z + w * q.w; +real_t Quat::dot(const Quat &p_q) const { + return x * p_q.x + y * p_q.y + z * p_q.z + w * p_q.w; } real_t Quat::length_squared() const { return dot(*this); } -void Quat::operator+=(const Quat &q) { - x += q.x; - y += q.y; - z += q.z; - w += q.w; +void Quat::operator+=(const Quat &p_q) { + x += p_q.x; + y += p_q.y; + z += p_q.z; + w += p_q.w; } -void Quat::operator-=(const Quat &q) { - x -= q.x; - y -= q.y; - z -= q.z; - w -= q.w; +void Quat::operator-=(const Quat &p_q) { + x -= p_q.x; + y -= p_q.y; + z -= p_q.z; + w -= p_q.w; } void Quat::operator*=(const real_t &s) { diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index 8ba1ba9286..ad28967d7a 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "quick_hull.h" -#include "core/map.h" +#include "core/templates/map.h" uint32_t QuickHull::debug_stop_after = 0xFFFFFFFF; diff --git a/core/math/quick_hull.h b/core/math/quick_hull.h index cac8e58d23..48ea139cc9 100644 --- a/core/math/quick_hull.h +++ b/core/math/quick_hull.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,17 +31,17 @@ #ifndef QUICK_HULL_H #define QUICK_HULL_H -#include "core/list.h" #include "core/math/aabb.h" #include "core/math/geometry_3d.h" -#include "core/set.h" +#include "core/templates/list.h" +#include "core/templates/set.h" class QuickHull { public: struct Edge { union { uint32_t vertices[2]; - uint64_t id; + uint64_t id = 0; }; bool operator<(const Edge &p_edge) const { @@ -60,7 +60,7 @@ public: struct Face { Plane plane; - uint32_t vertices[3]; + uint32_t vertices[3] = { 0 }; Vector<int> points_over; bool operator<(const Face &p_face) const { @@ -70,11 +70,13 @@ public: private: struct FaceConnect { - List<Face>::Element *left, *right = nullptr; + List<Face>::Element *left = nullptr; + List<Face>::Element *right = nullptr; FaceConnect() {} }; struct RetFaceConnect { - List<Geometry3D::MeshData::Face>::Element *left, *right = nullptr; + List<Geometry3D::MeshData::Face>::Element *left = nullptr; + List<Geometry3D::MeshData::Face>::Element *right = nullptr; RetFaceConnect() {} }; diff --git a/core/math/random_number_generator.cpp b/core/math/random_number_generator.cpp index 67f4c0b14a..b40d010219 100644 --- a/core/math/random_number_generator.cpp +++ b/core/math/random_number_generator.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +33,9 @@ void RandomNumberGenerator::_bind_methods() { ClassDB::bind_method(D_METHOD("set_seed", "seed"), &RandomNumberGenerator::set_seed); ClassDB::bind_method(D_METHOD("get_seed"), &RandomNumberGenerator::get_seed); - ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed"); + + ClassDB::bind_method(D_METHOD("set_state", "state"), &RandomNumberGenerator::set_state); + ClassDB::bind_method(D_METHOD("get_state"), &RandomNumberGenerator::get_state); ClassDB::bind_method(D_METHOD("randi"), &RandomNumberGenerator::randi); ClassDB::bind_method(D_METHOD("randf"), &RandomNumberGenerator::randf); @@ -41,4 +43,10 @@ void RandomNumberGenerator::_bind_methods() { ClassDB::bind_method(D_METHOD("randf_range", "from", "to"), &RandomNumberGenerator::randf_range); ClassDB::bind_method(D_METHOD("randi_range", "from", "to"), &RandomNumberGenerator::randi_range); ClassDB::bind_method(D_METHOD("randomize"), &RandomNumberGenerator::randomize); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "state"), "set_state", "get_state"); + // Default values are non-deterministic, override for doc generation purposes. + ADD_PROPERTY_DEFAULT("seed", 0); + ADD_PROPERTY_DEFAULT("state", 0); } diff --git a/core/math/random_number_generator.h b/core/math/random_number_generator.h index 920308e597..a396c2b7d7 100644 --- a/core/math/random_number_generator.h +++ b/core/math/random_number_generator.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,39 +32,30 @@ #define RANDOM_NUMBER_GENERATOR_H #include "core/math/random_pcg.h" -#include "core/reference.h" +#include "core/object/reference.h" class RandomNumberGenerator : public Reference { GDCLASS(RandomNumberGenerator, Reference); +protected: RandomPCG randbase; -protected: static void _bind_methods(); public: - _FORCE_INLINE_ void set_seed(uint64_t seed) { randbase.seed(seed); } - + _FORCE_INLINE_ void set_seed(uint64_t p_seed) { randbase.seed(p_seed); } _FORCE_INLINE_ uint64_t get_seed() { return randbase.get_seed(); } + _FORCE_INLINE_ void set_state(uint64_t p_state) { randbase.set_state(p_state); } + _FORCE_INLINE_ uint64_t get_state() const { return randbase.get_state(); } + _FORCE_INLINE_ void randomize() { randbase.randomize(); } _FORCE_INLINE_ uint32_t randi() { return randbase.rand(); } - _FORCE_INLINE_ real_t randf() { return randbase.randf(); } - - _FORCE_INLINE_ real_t randf_range(real_t from, real_t to) { return randbase.random(from, to); } - - _FORCE_INLINE_ real_t randfn(real_t mean = 0.0, real_t deviation = 1.0) { return randbase.randfn(mean, deviation); } - - _FORCE_INLINE_ int randi_range(int from, int to) { - unsigned int ret = randbase.rand(); - if (to < from) { - return ret % (from - to + 1) + to; - } else { - return ret % (to - from + 1) + from; - } - } + _FORCE_INLINE_ real_t randf_range(real_t p_from, real_t p_to) { return randbase.random(p_from, p_to); } + _FORCE_INLINE_ real_t randfn(real_t p_mean = 0.0, real_t p_deviation = 1.0) { return randbase.randfn(p_mean, p_deviation); } + _FORCE_INLINE_ int randi_range(int p_from, int p_to) { return randbase.random(p_from, p_to); } RandomNumberGenerator() {} }; diff --git a/core/math/random_pcg.cpp b/core/math/random_pcg.cpp index 02257c38d9..9609620469 100644 --- a/core/math/random_pcg.cpp +++ b/core/math/random_pcg.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -49,3 +49,10 @@ double RandomPCG::random(double p_from, double p_to) { float RandomPCG::random(float p_from, float p_to) { return randf() * (p_to - p_from) + p_from; } + +int RandomPCG::random(int p_from, int p_to) { + if (p_from == p_to) { + return p_from; + } + return rand(abs(p_from - p_to) + 1) + MIN(p_from, p_to); +} diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h index 09b13ab74d..5a03b758ce 100644 --- a/core/math/random_pcg.h +++ b/core/math/random_pcg.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -61,7 +61,7 @@ static int __bsr_clz32(uint32_t x) { class RandomPCG { pcg32_random_t pcg; - uint64_t current_seed; // seed with this to get the same state + uint64_t current_seed; // The seed the current generator state started from. uint64_t current_inc; public: @@ -76,11 +76,16 @@ public: } _FORCE_INLINE_ uint64_t get_seed() { return current_seed; } + _FORCE_INLINE_ void set_state(uint64_t p_state) { pcg.state = p_state; } + _FORCE_INLINE_ uint64_t get_state() const { return pcg.state; } + void randomize(); _FORCE_INLINE_ uint32_t rand() { - current_seed = pcg.state; return pcg32_random_r(&pcg); } + _FORCE_INLINE_ uint32_t rand(uint32_t bounds) { + return pcg32_boundedrand_r(&pcg, bounds); + } // Obtaining floating point numbers in [0, 1] range with "good enough" uniformity. // These functions sample the output of rand() as the fraction part of an infinite binary number, @@ -129,7 +134,7 @@ public: double random(double p_from, double p_to); float random(float p_from, float p_to); - real_t random(int p_from, int p_to) { return (real_t)random((real_t)p_from, (real_t)p_to); } + int random(int p_from, int p_to); }; #endif // RANDOM_PCG_H diff --git a/core/math/rect2.cpp b/core/math/rect2.cpp index 0cc3c4ca0f..60c44999f7 100644 --- a/core/math/rect2.cpp +++ b/core/math/rect2.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/rect2.h b/core/math/rect2.h index 14393325ec..512499bdb2 100644 --- a/core/math/rect2.h +++ b/core/math/rect2.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -123,8 +123,9 @@ struct Rect2 { _FORCE_INLINE_ bool has_no_area() const { return (size.x <= 0 || size.y <= 0); } - inline Rect2 clip(const Rect2 &p_rect) const { /// return a clipped rect + // Returns the instersection between two Rect2s or an empty Rect2 if there is no intersection + inline Rect2 intersection(const Rect2 &p_rect) const { Rect2 new_rect = p_rect; if (!intersects(new_rect)) { @@ -179,24 +180,28 @@ struct Rect2 { bool operator==(const Rect2 &p_rect) const { return position == p_rect.position && size == p_rect.size; } bool operator!=(const Rect2 &p_rect) const { return position != p_rect.position || size != p_rect.size; } - inline Rect2 grow(real_t p_by) const { + inline Rect2 grow(real_t p_amount) const { Rect2 g = *this; - g.position.x -= p_by; - g.position.y -= p_by; - g.size.width += p_by * 2; - g.size.height += p_by * 2; + g.position.x -= p_amount; + g.position.y -= p_amount; + g.size.width += p_amount * 2; + g.size.height += p_amount * 2; return g; } - inline Rect2 grow_margin(Margin p_margin, real_t p_amount) const { + inline Rect2 grow_side(Side p_side, real_t p_amount) const { Rect2 g = *this; - g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0, - (MARGIN_TOP == p_margin) ? p_amount : 0, - (MARGIN_RIGHT == p_margin) ? p_amount : 0, - (MARGIN_BOTTOM == p_margin) ? p_amount : 0); + g = g.grow_individual((SIDE_LEFT == p_side) ? p_amount : 0, + (SIDE_TOP == p_side) ? p_amount : 0, + (SIDE_RIGHT == p_side) ? p_amount : 0, + (SIDE_BOTTOM == p_side) ? p_amount : 0); return g; } + inline Rect2 grow_side_bind(uint32_t p_side, real_t p_amount) const { + return grow_side(Side(p_side), p_amount); + } + inline Rect2 grow_individual(real_t p_left, real_t p_top, real_t p_right, real_t p_bottom) const { Rect2 g = *this; g.position.x -= p_left; @@ -240,6 +245,77 @@ struct Rect2 { return Rect2(Point2(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs()); } + Vector2 get_support(const Vector2 &p_normal) const { + Vector2 half_extents = size * 0.5; + Vector2 ofs = position + half_extents; + return Vector2( + (p_normal.x > 0) ? -half_extents.x : half_extents.x, + (p_normal.y > 0) ? -half_extents.y : half_extents.y) + + ofs; + } + + _FORCE_INLINE_ bool intersects_filled_polygon(const Vector2 *p_points, int p_point_count) const { + Vector2 center = position + size * 0.5; + int side_plus = 0; + int side_minus = 0; + Vector2 end = position + size; + + int i_f = p_point_count - 1; + for (int i = 0; i < p_point_count; i++) { + const Vector2 &a = p_points[i_f]; + const Vector2 &b = p_points[i]; + i_f = i; + + Vector2 r = (b - a); + float l = r.length(); + if (l == 0.0) { + continue; + } + + //check inside + Vector2 tg = r.orthogonal(); + float s = tg.dot(center) - tg.dot(a); + if (s < 0.0) { + side_plus++; + } else { + side_minus++; + } + + //check ray box + r /= l; + Vector2 ir(1.0 / r.x, 1.0 / r.y); + + // lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner + // r.org is origin of ray + Vector2 t13 = (position - a) * ir; + Vector2 t24 = (end - a) * ir; + + float tmin = MAX(MIN(t13.x, t24.x), MIN(t13.y, t24.y)); + float tmax = MIN(MAX(t13.x, t24.x), MAX(t13.y, t24.y)); + + // if tmax < 0, ray (line) is intersecting AABB, but the whole AABB is behind us + if (tmax < 0 || tmin > tmax || tmin >= l) { + continue; + } + + return true; + } + + if (side_plus * side_minus == 0) { + return true; //all inside + } else { + return false; + } + } + + _FORCE_INLINE_ void set_end(const Vector2 &p_end) { + size = p_end - position; + } + + _FORCE_INLINE_ Vector2 get_end() const { + return position + size; + } + operator String() const { return String(position) + ", " + String(size); } Rect2() {} @@ -290,8 +366,9 @@ struct Rect2i { _FORCE_INLINE_ bool has_no_area() const { return (size.x <= 0 || size.y <= 0); } - inline Rect2i clip(const Rect2i &p_rect) const { /// return a clipped rect + // Returns the instersection between two Rect2is or an empty Rect2i if there is no intersection + inline Rect2i intersection(const Rect2i &p_rect) const { Rect2i new_rect = p_rect; if (!intersects(new_rect)) { @@ -301,8 +378,8 @@ struct Rect2i { new_rect.position.x = MAX(p_rect.position.x, position.x); new_rect.position.y = MAX(p_rect.position.y, position.y); - Point2 p_rect_end = p_rect.position + p_rect.size; - Point2 end = position + size; + Point2i p_rect_end = p_rect.position + p_rect.size; + Point2i end = position + size; new_rect.size.x = (int)(MIN(p_rect_end.x, end.x) - new_rect.position.x); new_rect.size.y = (int)(MIN(p_rect_end.y, end.y) - new_rect.position.y); @@ -324,7 +401,7 @@ struct Rect2i { return new_rect; } - bool has_point(const Point2 &p_point) const { + bool has_point(const Point2i &p_point) const { if (p_point.x < position.x) { return false; } @@ -345,24 +422,28 @@ struct Rect2i { bool operator==(const Rect2i &p_rect) const { return position == p_rect.position && size == p_rect.size; } bool operator!=(const Rect2i &p_rect) const { return position != p_rect.position || size != p_rect.size; } - Rect2i grow(int p_by) const { + Rect2i grow(int p_amount) const { Rect2i g = *this; - g.position.x -= p_by; - g.position.y -= p_by; - g.size.width += p_by * 2; - g.size.height += p_by * 2; + g.position.x -= p_amount; + g.position.y -= p_amount; + g.size.width += p_amount * 2; + g.size.height += p_amount * 2; return g; } - inline Rect2i grow_margin(Margin p_margin, int p_amount) const { + inline Rect2i grow_side(Side p_side, int p_amount) const { Rect2i g = *this; - g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0, - (MARGIN_TOP == p_margin) ? p_amount : 0, - (MARGIN_RIGHT == p_margin) ? p_amount : 0, - (MARGIN_BOTTOM == p_margin) ? p_amount : 0); + g = g.grow_individual((SIDE_LEFT == p_side) ? p_amount : 0, + (SIDE_TOP == p_side) ? p_amount : 0, + (SIDE_RIGHT == p_side) ? p_amount : 0, + (SIDE_BOTTOM == p_side) ? p_amount : 0); return g; } + inline Rect2i grow_side_bind(uint32_t p_side, int p_amount) const { + return grow_side(Side(p_side), p_amount); + } + inline Rect2i grow_individual(int p_left, int p_top, int p_right, int p_bottom) const { Rect2i g = *this; g.position.x -= p_left; @@ -405,6 +486,14 @@ struct Rect2i { return Rect2i(Point2i(position.x + MIN(size.x, 0), position.y + MIN(size.y, 0)), size.abs()); } + _FORCE_INLINE_ void set_end(const Vector2i &p_end) { + size = p_end - position; + } + + _FORCE_INLINE_ Vector2i get_end() const { + return position + size; + } + operator String() const { return String(position) + ", " + String(size); } operator Rect2() const { return Rect2(position, size); } @@ -415,10 +504,10 @@ struct Rect2i { size(p_r2.size) { } Rect2i(int p_x, int p_y, int p_width, int p_height) : - position(Point2(p_x, p_y)), - size(Size2(p_width, p_height)) { + position(Point2i(p_x, p_y)), + size(Size2i(p_width, p_height)) { } - Rect2i(const Point2 &p_pos, const Size2 &p_size) : + Rect2i(const Point2i &p_pos, const Size2i &p_size) : position(p_pos), size(p_size) { } diff --git a/core/math/transform.cpp b/core/math/transform.cpp index 0274dd18af..fab5d124fa 100644 --- a/core/math/transform.cpp +++ b/core/math/transform.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,7 @@ #include "core/math/math_funcs.h" #include "core/os/copymem.h" -#include "core/print_string.h" +#include "core/string/print_string.h" void Transform::affine_invert() { basis.invert(); @@ -200,6 +200,13 @@ Transform::Transform(const Basis &p_basis, const Vector3 &p_origin) : origin(p_origin) { } +Transform::Transform(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin) : + origin(p_origin) { + basis.set_axis(0, p_x); + basis.set_axis(1, p_y); + basis.set_axis(2, p_z); +} + Transform::Transform(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz) { basis = Basis(xx, xy, xz, yx, yy, yz, zx, zy, zz); origin = Vector3(ox, oy, oz); diff --git a/core/math/transform.h b/core/math/transform.h index 71847d36ac..b121ef984a 100644 --- a/core/math/transform.h +++ b/core/math/transform.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -106,9 +106,10 @@ public: operator String() const; - Transform(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz); - Transform(const Basis &p_basis, const Vector3 &p_origin = Vector3()); Transform() {} + Transform(const Basis &p_basis, const Vector3 &p_origin = Vector3()); + Transform(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin); + Transform(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz); }; _FORCE_INLINE_ Vector3 Transform::xform(const Vector3 &p_vector) const { diff --git a/core/math/transform_2d.cpp b/core/math/transform_2d.cpp index 180aeaa0af..4a521b96ae 100644 --- a/core/math/transform_2d.cpp +++ b/core/math/transform_2d.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -251,7 +251,7 @@ Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, real_t real_t dot = v1.dot(v2); - dot = (dot < -1.0) ? -1.0 : ((dot > 1.0) ? 1.0 : dot); //clamp dot to [-1,1] + dot = CLAMP(dot, -1.0, 1.0); Vector2 v; diff --git a/core/math/transform_2d.h b/core/math/transform_2d.h index 46e97abaa7..327d0f244f 100644 --- a/core/math/transform_2d.h +++ b/core/math/transform_2d.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -128,6 +128,12 @@ struct Transform2D { elements[2][1] = oy; } + Transform2D(const Vector2 &p_x, const Vector2 &p_y, const Vector2 &p_origin) { + elements[0] = p_x; + elements[1] = p_y; + elements[2] = p_origin; + } + Transform2D(real_t p_rot, const Vector2 &p_pos); Transform2D() { elements[0][0] = 1.0; diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp index c9a546e385..23c0c686a2 100644 --- a/core/math/triangle_mesh.cpp +++ b/core/math/triangle_mesh.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "triangle_mesh.h" -#include "core/sort_array.h" +#include "core/templates/sort_array.h" int TriangleMesh::_create_bvh(BVH *p_bvh, BVH **p_bb, int p_from, int p_size, int p_depth, int &max_depth, int &max_alloc) { if (p_depth > max_depth) { diff --git a/core/math/triangle_mesh.h b/core/math/triangle_mesh.h index 86412cf725..1d1dbc114b 100644 --- a/core/math/triangle_mesh.h +++ b/core/math/triangle_mesh.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,7 @@ #define TRIANGLE_MESH_H #include "core/math/face3.h" -#include "core/reference.h" +#include "core/object/reference.h" class TriangleMesh : public Reference { GDCLASS(TriangleMesh, Reference); diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp index 12bd384c6a..0047c0705d 100644 --- a/core/math/triangulate.cpp +++ b/core/math/triangulate.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/triangulate.h b/core/math/triangulate.h index c453b77ecf..55dc4e8e7d 100644 --- a/core/math/triangulate.h +++ b/core/math/triangulate.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/vector2.cpp b/core/math/vector2.cpp index 233421e070..496e29ebe4 100644 --- a/core/math/vector2.cpp +++ b/core/math/vector2.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -118,14 +118,14 @@ Vector2 Vector2::posmodv(const Vector2 &p_modv) const { return Vector2(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y)); } -Vector2 Vector2::project(const Vector2 &p_b) const { - return p_b * (dot(p_b) / p_b.length_squared()); +Vector2 Vector2::project(const Vector2 &p_to) const { + return p_to * (dot(p_to) / p_to.length_squared()); } -Vector2 Vector2::snapped(const Vector2 &p_by) const { +Vector2 Vector2::snapped(const Vector2 &p_step) const { return Vector2( - Math::stepify(x, p_by.x), - Math::stepify(y, p_by.y)); + Math::snapped(x, p_step.x), + Math::snapped(y, p_step.y)); } Vector2 Vector2::clamped(real_t p_len) const { @@ -139,13 +139,13 @@ Vector2 Vector2::clamped(real_t p_len) const { return v; } -Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const { +Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight) const { Vector2 p0 = p_pre_a; Vector2 p1 = *this; Vector2 p2 = p_b; Vector2 p3 = p_post_b; - real_t t = p_t; + real_t t = p_weight; real_t t2 = t * t; real_t t3 = t2 * t; @@ -233,6 +233,19 @@ void Vector2i::operator/=(const int &rvalue) { y /= rvalue; } +Vector2i Vector2i::operator%(const Vector2i &p_v1) const { + return Vector2i(x % p_v1.x, y % p_v1.y); +} + +Vector2i Vector2i::operator%(const int &rvalue) const { + return Vector2i(x % rvalue, y % rvalue); +} + +void Vector2i::operator%=(const int &rvalue) { + x %= rvalue; + y %= rvalue; +} + Vector2i Vector2i::operator-() const { return Vector2i(-x, -y); } diff --git a/core/math/vector2.h b/core/math/vector2.h index c2a2656e72..24795857a3 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,7 @@ #define VECTOR2_H #include "core/math/math_funcs.h" -#include "core/ustring.h" +#include "core/string/ustring.h" struct Vector2i; @@ -77,21 +77,21 @@ struct Vector2 { real_t distance_squared_to(const Vector2 &p_vector2) const; real_t angle_to(const Vector2 &p_vector2) const; real_t angle_to_point(const Vector2 &p_vector2) const; - _FORCE_INLINE_ Vector2 direction_to(const Vector2 &p_b) const; + _FORCE_INLINE_ Vector2 direction_to(const Vector2 &p_to) const; real_t dot(const Vector2 &p_other) const; real_t cross(const Vector2 &p_other) const; Vector2 posmod(const real_t p_mod) const; Vector2 posmodv(const Vector2 &p_modv) const; - Vector2 project(const Vector2 &p_b) const; + Vector2 project(const Vector2 &p_to) const; Vector2 plane_project(real_t p_d, const Vector2 &p_vec) const; Vector2 clamped(real_t p_len) const; - _FORCE_INLINE_ Vector2 lerp(const Vector2 &p_b, real_t p_t) const; - _FORCE_INLINE_ Vector2 slerp(const Vector2 &p_b, real_t p_t) const; - Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_t) const; + _FORCE_INLINE_ Vector2 lerp(const Vector2 &p_to, real_t p_weight) const; + _FORCE_INLINE_ Vector2 slerp(const Vector2 &p_to, real_t p_weight) const; + Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight) const; Vector2 move_toward(const Vector2 &p_to, const real_t p_delta) const; Vector2 slide(const Vector2 &p_normal) const; @@ -134,7 +134,7 @@ struct Vector2 { } Vector2 rotated(real_t p_by) const; - Vector2 tangent() const { + Vector2 orthogonal() const { return Vector2(y, -x); } @@ -230,25 +230,25 @@ _FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const { return x != p_vec2.x || y != p_vec2.y; } -Vector2 Vector2::lerp(const Vector2 &p_b, real_t p_t) const { +Vector2 Vector2::lerp(const Vector2 &p_to, real_t p_weight) const { Vector2 res = *this; - res.x += (p_t * (p_b.x - x)); - res.y += (p_t * (p_b.y - y)); + res.x += (p_weight * (p_to.x - x)); + res.y += (p_weight * (p_to.y - y)); return res; } -Vector2 Vector2::slerp(const Vector2 &p_b, real_t p_t) const { +Vector2 Vector2::slerp(const Vector2 &p_to, real_t p_weight) const { #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(!is_normalized(), Vector2(), "The start Vector2 must be normalized."); #endif - real_t theta = angle_to(p_b); - return rotated(theta * p_t); + real_t theta = angle_to(p_to); + return rotated(theta * p_weight); } -Vector2 Vector2::direction_to(const Vector2 &p_b) const { - Vector2 ret(p_b.x - x, p_b.y - y); +Vector2 Vector2::direction_to(const Vector2 &p_to) const { + Vector2 ret(p_to.x - x, p_to.y - y); ret.normalize(); return ret; } @@ -290,11 +290,13 @@ struct Vector2i { void operator*=(const int &rvalue); Vector2i operator/(const Vector2i &p_v1) const; - Vector2i operator/(const int &rvalue) const; - void operator/=(const int &rvalue); + Vector2i operator%(const Vector2i &p_v1) const; + Vector2i operator%(const int &rvalue) const; + void operator%=(const int &rvalue); + Vector2i operator-() const; bool operator<(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); } bool operator>(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y > p_vec2.y) : (x > p_vec2.x); } diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index 568df48c62..f0629d3db8 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -60,58 +60,25 @@ int Vector3::max_axis() const { return x < y ? (y < z ? 2 : 1) : (x < z ? 2 : 0); } -void Vector3::snap(Vector3 p_val) { - x = Math::stepify(x, p_val.x); - y = Math::stepify(y, p_val.y); - z = Math::stepify(z, p_val.z); +void Vector3::snap(Vector3 p_step) { + x = Math::snapped(x, p_step.x); + y = Math::snapped(y, p_step.y); + z = Math::snapped(z, p_step.z); } -Vector3 Vector3::snapped(Vector3 p_val) const { +Vector3 Vector3::snapped(Vector3 p_step) const { Vector3 v = *this; - v.snap(p_val); + v.snap(p_step); return v; } -Vector3 Vector3::cubic_interpolaten(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_t) const { +Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight) const { Vector3 p0 = p_pre_a; Vector3 p1 = *this; Vector3 p2 = p_b; Vector3 p3 = p_post_b; - { - //normalize - - real_t ab = p0.distance_to(p1); - real_t bc = p1.distance_to(p2); - real_t cd = p2.distance_to(p3); - - if (ab > 0) { - p0 = p1 + (p0 - p1) * (bc / ab); - } - if (cd > 0) { - p3 = p2 + (p3 - p2) * (bc / cd); - } - } - - real_t t = p_t; - real_t t2 = t * t; - real_t t3 = t2 * t; - - Vector3 out; - out = 0.5 * ((p1 * 2.0) + - (-p0 + p2) * t + - (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t2 + - (-p0 + 3.0 * p1 - 3.0 * p2 + p3) * t3); - return out; -} - -Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_t) const { - Vector3 p0 = p_pre_a; - Vector3 p1 = *this; - Vector3 p2 = p_b; - Vector3 p3 = p_post_b; - - real_t t = p_t; + real_t t = p_weight; real_t t2 = t * t; real_t t3 = t2 * t; diff --git a/core/math/vector3.h b/core/math/vector3.h index 5370b297f1..3fdb944729 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +33,7 @@ #include "core/math/math_funcs.h" #include "core/math/vector3i.h" -#include "core/ustring.h" +#include "core/string/ustring.h" class Basis; @@ -86,10 +86,9 @@ struct Vector3 { /* Static Methods between 2 vector3s */ - _FORCE_INLINE_ Vector3 lerp(const Vector3 &p_b, real_t p_t) const; - _FORCE_INLINE_ Vector3 slerp(const Vector3 &p_b, real_t p_t) const; - Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_t) const; - Vector3 cubic_interpolaten(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_t) const; + _FORCE_INLINE_ Vector3 lerp(const Vector3 &p_to, real_t p_weight) const; + _FORCE_INLINE_ Vector3 slerp(const Vector3 &p_to, real_t p_weight) const; + Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight) const; Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const; _FORCE_INLINE_ Vector3 cross(const Vector3 &p_b) const; @@ -103,15 +102,15 @@ struct Vector3 { _FORCE_INLINE_ Vector3 ceil() const; _FORCE_INLINE_ Vector3 round() const; - _FORCE_INLINE_ real_t distance_to(const Vector3 &p_b) const; - _FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_b) const; + _FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const; + _FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const; _FORCE_INLINE_ Vector3 posmod(const real_t p_mod) const; _FORCE_INLINE_ Vector3 posmodv(const Vector3 &p_modv) const; - _FORCE_INLINE_ Vector3 project(const Vector3 &p_b) const; + _FORCE_INLINE_ Vector3 project(const Vector3 &p_to) const; - _FORCE_INLINE_ real_t angle_to(const Vector3 &p_b) const; - _FORCE_INLINE_ Vector3 direction_to(const Vector3 &p_b) const; + _FORCE_INLINE_ real_t angle_to(const Vector3 &p_to) const; + _FORCE_INLINE_ Vector3 direction_to(const Vector3 &p_to) const; _FORCE_INLINE_ Vector3 slide(const Vector3 &p_normal) const; _FORCE_INLINE_ Vector3 bounce(const Vector3 &p_normal) const; @@ -195,24 +194,24 @@ Vector3 Vector3::round() const { return Vector3(Math::round(x), Math::round(y), Math::round(z)); } -Vector3 Vector3::lerp(const Vector3 &p_b, real_t p_t) const { +Vector3 Vector3::lerp(const Vector3 &p_to, real_t p_weight) const { return Vector3( - x + (p_t * (p_b.x - x)), - y + (p_t * (p_b.y - y)), - z + (p_t * (p_b.z - z))); + x + (p_weight * (p_to.x - x)), + y + (p_weight * (p_to.y - y)), + z + (p_weight * (p_to.z - z))); } -Vector3 Vector3::slerp(const Vector3 &p_b, real_t p_t) const { - real_t theta = angle_to(p_b); - return rotated(cross(p_b).normalized(), theta * p_t); +Vector3 Vector3::slerp(const Vector3 &p_to, real_t p_weight) const { + real_t theta = angle_to(p_to); + return rotated(cross(p_to).normalized(), theta * p_weight); } -real_t Vector3::distance_to(const Vector3 &p_b) const { - return (p_b - *this).length(); +real_t Vector3::distance_to(const Vector3 &p_to) const { + return (p_to - *this).length(); } -real_t Vector3::distance_squared_to(const Vector3 &p_b) const { - return (p_b - *this).length_squared(); +real_t Vector3::distance_squared_to(const Vector3 &p_to) const { + return (p_to - *this).length_squared(); } Vector3 Vector3::posmod(const real_t p_mod) const { @@ -223,16 +222,16 @@ Vector3 Vector3::posmodv(const Vector3 &p_modv) const { return Vector3(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y), Math::fposmod(z, p_modv.z)); } -Vector3 Vector3::project(const Vector3 &p_b) const { - return p_b * (dot(p_b) / p_b.length_squared()); +Vector3 Vector3::project(const Vector3 &p_to) const { + return p_to * (dot(p_to) / p_to.length_squared()); } -real_t Vector3::angle_to(const Vector3 &p_b) const { - return Math::atan2(cross(p_b).length(), dot(p_b)); +real_t Vector3::angle_to(const Vector3 &p_to) const { + return Math::atan2(cross(p_to).length(), dot(p_to)); } -Vector3 Vector3::direction_to(const Vector3 &p_b) const { - Vector3 ret(p_b.x - x, p_b.y - y, p_b.z - z); +Vector3 Vector3::direction_to(const Vector3 &p_to) const { + Vector3 ret(p_to.x - x, p_to.y - y, p_to.z - z); ret.normalize(); return ret; } diff --git a/core/math/vector3i.cpp b/core/math/vector3i.cpp index 718a1553a0..167fa3221d 100644 --- a/core/math/vector3i.cpp +++ b/core/math/vector3i.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/vector3i.h b/core/math/vector3i.h index 08729ad056..b0411fb62e 100644 --- a/core/math/vector3i.h +++ b/core/math/vector3i.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef VECTOR3I_H #define VECTOR3I_H +#include "core/string/ustring.h" #include "core/typedefs.h" -#include "core/ustring.h" struct Vector3i { enum Axis { @@ -80,11 +80,15 @@ struct Vector3i { _FORCE_INLINE_ Vector3i operator*(const Vector3i &p_v) const; _FORCE_INLINE_ Vector3i &operator/=(const Vector3i &p_v); _FORCE_INLINE_ Vector3i operator/(const Vector3i &p_v) const; + _FORCE_INLINE_ Vector3i &operator%=(const Vector3i &p_v); + _FORCE_INLINE_ Vector3i operator%(const Vector3i &p_v) const; _FORCE_INLINE_ Vector3i &operator*=(int32_t p_scalar); _FORCE_INLINE_ Vector3i operator*(int32_t p_scalar) const; _FORCE_INLINE_ Vector3i &operator/=(int32_t p_scalar); _FORCE_INLINE_ Vector3i operator/(int32_t p_scalar) const; + _FORCE_INLINE_ Vector3i &operator%=(int32_t p_scalar); + _FORCE_INLINE_ Vector3i operator%(int32_t p_scalar) const; _FORCE_INLINE_ Vector3i operator-() const; @@ -159,6 +163,17 @@ Vector3i Vector3i::operator/(const Vector3i &p_v) const { return Vector3i(x / p_v.x, y / p_v.y, z / p_v.z); } +Vector3i &Vector3i::operator%=(const Vector3i &p_v) { + x %= p_v.x; + y %= p_v.y; + z %= p_v.z; + return *this; +} + +Vector3i Vector3i::operator%(const Vector3i &p_v) const { + return Vector3i(x % p_v.x, y % p_v.y, z % p_v.z); +} + Vector3i &Vector3i::operator*=(int32_t p_scalar) { x *= p_scalar; y *= p_scalar; @@ -185,6 +200,17 @@ Vector3i Vector3i::operator/(int32_t p_scalar) const { return Vector3i(x / p_scalar, y / p_scalar, z / p_scalar); } +Vector3i &Vector3i::operator%=(int32_t p_scalar) { + x %= p_scalar; + y %= p_scalar; + z %= p_scalar; + return *this; +} + +Vector3i Vector3i::operator%(int32_t p_scalar) const { + return Vector3i(x % p_scalar, y % p_scalar, z % p_scalar); +} + Vector3i Vector3i::operator-() const { return Vector3i(-x, -y, -z); } diff --git a/core/method_bind.h b/core/method_bind.h deleted file mode 100644 index 942e2e0036..0000000000 --- a/core/method_bind.h +++ /dev/null @@ -1,393 +0,0 @@ -/*************************************************************************/ -/* method_bind.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef METHOD_BIND_H -#define METHOD_BIND_H - -#ifdef DEBUG_ENABLED -#define DEBUG_METHODS_ENABLED -#endif - -#include "core/list.h" -#include "core/method_ptrcall.h" -#include "core/object.h" -#include "core/type_info.h" -#include "core/typedefs.h" -#include "core/variant.h" - -#include <stdio.h> - -enum MethodFlags { - - METHOD_FLAG_NORMAL = 1, - METHOD_FLAG_EDITOR = 2, - METHOD_FLAG_NOSCRIPT = 4, - METHOD_FLAG_CONST = 8, - METHOD_FLAG_REVERSE = 16, // used for events - METHOD_FLAG_VIRTUAL = 32, - METHOD_FLAG_FROM_SCRIPT = 64, - METHOD_FLAG_VARARG = 128, - METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL, -}; - -template <class T> -struct VariantCaster { - static _FORCE_INLINE_ T cast(const Variant &p_variant) { - return p_variant; - } -}; - -template <class T> -struct VariantCaster<T &> { - static _FORCE_INLINE_ T cast(const Variant &p_variant) { - return p_variant; - } -}; - -template <class T> -struct VariantCaster<const T &> { - static _FORCE_INLINE_ T cast(const Variant &p_variant) { - return p_variant; - } -}; - -#define _VC(m_idx) \ - (VariantCaster<P##m_idx>::cast((m_idx - 1) >= p_arg_count ? get_default_argument(m_idx - 1) : *p_args[m_idx - 1])) - -#ifdef PTRCALL_ENABLED - -#define VARIANT_ENUM_CAST(m_enum) \ - MAKE_ENUM_TYPE_INFO(m_enum) \ - template <> \ - struct VariantCaster<m_enum> { \ - static _FORCE_INLINE_ m_enum cast(const Variant &p_variant) { \ - return (m_enum)p_variant.operator int(); \ - } \ - }; \ - template <> \ - struct PtrToArg<m_enum> { \ - _FORCE_INLINE_ static m_enum convert(const void *p_ptr) { \ - return m_enum(*reinterpret_cast<const int *>(p_ptr)); \ - } \ - _FORCE_INLINE_ static void encode(m_enum p_val, const void *p_ptr) { \ - *(int *)p_ptr = p_val; \ - } \ - }; - -#else - -#define VARIANT_ENUM_CAST(m_enum) \ - MAKE_ENUM_TYPE_INFO(m_enum) \ - template <> \ - struct VariantCaster<m_enum> { \ - static _FORCE_INLINE_ m_enum cast(const Variant &p_variant) { \ - return (m_enum)p_variant.operator int(); \ - } \ - }; - -#endif - -// Object enum casts must go here -VARIANT_ENUM_CAST(Object::ConnectFlags); - -template <typename T> -struct VariantObjectClassChecker { - static _FORCE_INLINE_ bool check(const Variant &p_variant) { - return true; - } -}; - -template <> -struct VariantObjectClassChecker<Node *> { - static _FORCE_INLINE_ bool check(const Variant &p_variant) { - Object *obj = p_variant; - Node *node = p_variant; - return node || !obj; - } -}; - -template <> -struct VariantObjectClassChecker<Control *> { - static _FORCE_INLINE_ bool check(const Variant &p_variant) { - Object *obj = p_variant; - Control *control = p_variant; - return control || !obj; - } -}; - -#define CHECK_ARG(m_arg) \ - if ((m_arg - 1) < p_arg_count) { \ - Variant::Type argtype = get_argument_type(m_arg - 1); \ - if (!Variant::can_convert_strict(p_args[m_arg - 1]->get_type(), argtype) || \ - !VariantObjectClassChecker<P##m_arg>::check(*p_args[m_arg - 1])) { \ - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; \ - r_error.argument = m_arg - 1; \ - r_error.expected = argtype; \ - return Variant(); \ - } \ - } - -#define CHECK_NOARG(m_arg) \ - { \ - if (p_arg##m_arg.get_type() != Variant::NIL) { \ - if (r_argerror) { \ - *r_argerror = (m_arg - 1); \ - } \ - return CALL_ERROR_EXTRA_ARGUMENT; \ - } \ - } - -// some helpers - -VARIANT_ENUM_CAST(Vector3::Axis); - -VARIANT_ENUM_CAST(Error); -VARIANT_ENUM_CAST(Margin); -VARIANT_ENUM_CAST(Corner); -VARIANT_ENUM_CAST(Orientation); -VARIANT_ENUM_CAST(HAlign); -VARIANT_ENUM_CAST(VAlign); -VARIANT_ENUM_CAST(PropertyHint); -VARIANT_ENUM_CAST(PropertyUsageFlags); -VARIANT_ENUM_CAST(MethodFlags); -VARIANT_ENUM_CAST(Variant::Type); -VARIANT_ENUM_CAST(Variant::Operator); - -template <> -struct VariantCaster<char32_t> { - static _FORCE_INLINE_ char32_t cast(const Variant &p_variant) { - return (char32_t)p_variant.operator int(); - } -}; -#ifdef PTRCALL_ENABLED -template <> -struct PtrToArg<char32_t> { - _FORCE_INLINE_ static char32_t convert(const void *p_ptr) { - return char32_t(*reinterpret_cast<const int *>(p_ptr)); - } - _FORCE_INLINE_ static void encode(char32_t p_val, const void *p_ptr) { - *(int *)p_ptr = p_val; - } -}; -#endif - -class MethodBind { - int method_id; - uint32_t hint_flags = METHOD_FLAGS_DEFAULT; - StringName name; - Vector<Variant> default_arguments; - int default_argument_count = 0; - int argument_count = 0; - - bool _const = false; - bool _returns = false; - -protected: -#ifdef DEBUG_METHODS_ENABLED - Variant::Type *argument_types = nullptr; - Vector<StringName> arg_names; -#endif - void _set_const(bool p_const); - void _set_returns(bool p_returns); -#ifdef DEBUG_METHODS_ENABLED - virtual Variant::Type _gen_argument_type(int p_arg) const = 0; - virtual PropertyInfo _gen_argument_type_info(int p_arg) const = 0; - void _generate_argument_types(int p_count); - -#endif - void set_argument_count(int p_count) { argument_count = p_count; } - -public: - Vector<Variant> get_default_arguments() const { return default_arguments; } - _FORCE_INLINE_ int get_default_argument_count() const { return default_argument_count; } - - _FORCE_INLINE_ Variant has_default_argument(int p_arg) const { - int idx = argument_count - p_arg - 1; - - if (idx < 0 || idx >= default_arguments.size()) { - return false; - } else { - return true; - } - } - - _FORCE_INLINE_ Variant get_default_argument(int p_arg) const { - int idx = argument_count - p_arg - 1; - - if (idx < 0 || idx >= default_arguments.size()) { - return Variant(); - } else { - return default_arguments[idx]; - } - } - -#ifdef DEBUG_METHODS_ENABLED - - _FORCE_INLINE_ Variant::Type get_argument_type(int p_argument) const { - ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, Variant::NIL); - return argument_types[p_argument + 1]; - } - - PropertyInfo get_argument_info(int p_argument) const; - PropertyInfo get_return_info() const; - - void set_argument_names(const Vector<StringName> &p_names); //set by class, db, can't be inferred otherwise - Vector<StringName> get_argument_names() const; - - virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const = 0; - -#endif - void set_hint_flags(uint32_t p_hint) { hint_flags = p_hint; } - uint32_t get_hint_flags() const { return hint_flags | (is_const() ? METHOD_FLAG_CONST : 0) | (is_vararg() ? METHOD_FLAG_VARARG : 0); } - virtual String get_instance_class() const = 0; - - _FORCE_INLINE_ int get_argument_count() const { return argument_count; }; - - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) = 0; - -#ifdef PTRCALL_ENABLED - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) = 0; -#endif - - StringName get_name() const; - void set_name(const StringName &p_name); - _FORCE_INLINE_ int get_method_id() const { return method_id; } - _FORCE_INLINE_ bool is_const() const { return _const; } - _FORCE_INLINE_ bool has_return() const { return _returns; } - virtual bool is_vararg() const { return false; } - - void set_default_arguments(const Vector<Variant> &p_defargs); - - MethodBind(); - virtual ~MethodBind(); -}; - -template <class T> -class MethodBindVarArg : public MethodBind { -public: - typedef Variant (T::*NativeCall)(const Variant **, int, Callable::CallError &); - -protected: - NativeCall call_method = nullptr; -#ifdef DEBUG_METHODS_ENABLED - MethodInfo arguments; -#endif - -public: -#ifdef DEBUG_METHODS_ENABLED - - virtual PropertyInfo _gen_argument_type_info(int p_arg) const { - if (p_arg < 0) { - return arguments.return_val; - } else if (p_arg < arguments.arguments.size()) { - return arguments.arguments[p_arg]; - } else { - return PropertyInfo(Variant::NIL, "arg_" + itos(p_arg), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); - } - } - - virtual Variant::Type _gen_argument_type(int p_arg) const { - return _gen_argument_type_info(p_arg).type; - } - - virtual GodotTypeInfo::Metadata get_argument_meta(int) const { - return GodotTypeInfo::METADATA_NONE; - } - -#else - - virtual Variant::Type _gen_argument_type(int p_arg) const { - return Variant::NIL; - } - -#endif - virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { - T *instance = static_cast<T *>(p_object); - return (instance->*call_method)(p_args, p_arg_count, r_error); - } - - void set_method_info(const MethodInfo &p_info, bool p_return_nil_is_variant) { - set_argument_count(p_info.arguments.size()); -#ifdef DEBUG_METHODS_ENABLED - Variant::Type *at = memnew_arr(Variant::Type, p_info.arguments.size() + 1); - at[0] = p_info.return_val.type; - if (p_info.arguments.size()) { - Vector<StringName> names; - names.resize(p_info.arguments.size()); - for (int i = 0; i < p_info.arguments.size(); i++) { - at[i + 1] = p_info.arguments[i].type; - names.write[i] = p_info.arguments[i].name; - } - - set_argument_names(names); - } - argument_types = at; - arguments = p_info; - if (p_return_nil_is_variant) { - arguments.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; - } -#endif - } - -#ifdef PTRCALL_ENABLED - virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { - ERR_FAIL(); //can't call - } //todo -#endif - - void set_method(NativeCall p_method) { call_method = p_method; } - virtual bool is_const() const { return false; } - virtual String get_instance_class() const { return T::get_class_static(); } - - virtual bool is_vararg() const { return true; } - - MethodBindVarArg() { - _set_returns(true); - } -}; - -template <class T> -MethodBind *create_vararg_method_bind(Variant (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) { - MethodBindVarArg<T> *a = memnew((MethodBindVarArg<T>)); - a->set_method(p_method); - a->set_method_info(p_info, p_return_nil_is_variant); - return a; -} - -/** This amazing hack is based on the FastDelegates theory */ - -// tale of an amazing hack.. // - -// if you declare a nonexistent class.. -class __UnexistingClass; - -#include "method_bind.gen.inc" - -#endif // METHOD_BIND_H diff --git a/core/object/SCsub b/core/object/SCsub new file mode 100644 index 0000000000..5d429960e5 --- /dev/null +++ b/core/object/SCsub @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +Import("env") + +env_object = env.Clone() + +env_object.add_source_files(env.core_sources, "*.cpp") diff --git a/core/callable_method_pointer.cpp b/core/object/callable_method_pointer.cpp index 21a917cbd7..2bfaef744d 100644 --- a/core/callable_method_pointer.cpp +++ b/core/object/callable_method_pointer.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/callable_method_pointer.h b/core/object/callable_method_pointer.h index 1bb89e53e1..115797a00c 100644 --- a/core/callable_method_pointer.h +++ b/core/object/callable_method_pointer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,11 +31,12 @@ #ifndef CALLABLE_METHOD_POINTER_H #define CALLABLE_METHOD_POINTER_H -#include "core/callable.h" -#include "core/hashfuncs.h" -#include "core/object.h" +#include "core/object/object.h" #include "core/os/copymem.h" -#include "core/simple_type.h" +#include "core/templates/hashfuncs.h" +#include "core/templates/simple_type.h" +#include "core/variant/binder_common.h" +#include "core/variant/callable.h" class CallableCustomMethodPointerBase : public CallableCustom { uint32_t *comp_ptr; @@ -69,94 +70,6 @@ public: virtual uint32_t hash() const; }; -#ifdef DEBUG_METHODS_ENABLED - -template <class T> -struct VariantCasterAndValidate { - static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { - Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE; - if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype)) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = p_arg_idx; - r_error.expected = argtype; - } - - return VariantCaster<T>::cast(*p_args[p_arg_idx]); - } -}; - -template <class T> -struct VariantCasterAndValidate<T &> { - static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { - Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE; - if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype)) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = p_arg_idx; - r_error.expected = argtype; - } - - return VariantCaster<T>::cast(*p_args[p_arg_idx]); - } -}; - -template <class T> -struct VariantCasterAndValidate<const T &> { - static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { - Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE; - if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype)) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = p_arg_idx; - r_error.expected = argtype; - } - - return VariantCaster<T>::cast(*p_args[p_arg_idx]); - } -}; - -#endif // DEBUG_METHODS_ENABLED - -// GCC 8 raises "parameter 'p_args' set but not used" here, probably using a -// template version that does not have arguments and thus sees it unused, but -// obviously the template can be used for functions with and without them, and -// the optimizer will get rid of it anyway. -#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-but-set-parameter" -#endif - -template <class T, class... P, size_t... Is> -void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) { - r_error.error = Callable::CallError::CALL_OK; - -#ifdef DEBUG_METHODS_ENABLED - (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); -#else - (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...); -#endif -} - -#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif - -template <class T, class... P> -void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error) { -#ifdef DEBUG_METHODS_ENABLED - if ((size_t)p_argcount > sizeof...(P)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); - return; - } - - if ((size_t)p_argcount < sizeof...(P)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); - return; - } -#endif - call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{}); -} - template <class T, class... P> class CallableCustomMethodPointer : public CallableCustomMethodPointerBase { struct Data { @@ -201,7 +114,6 @@ Callable create_custom_callable_function_pointer(T *p_instance, const char *p_func_text, #endif void (T::*p_method)(P...)) { - typedef CallableCustomMethodPointer<T, P...> CCMP; // Messes with memnew otherwise. CCMP *ccmp = memnew(CCMP(p_instance, p_method)); #ifdef DEBUG_METHODS_ENABLED @@ -212,57 +124,70 @@ Callable create_custom_callable_function_pointer(T *p_instance, // VERSION WITH RETURN -// GCC 8 raises "parameter 'p_args' set but not used" here, probably using a -// template version that does not have arguments and thus sees it unused, but -// obviously the template can be used for functions with and without them, and -// the optimizer will get rid of it anyway. -#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-but-set-parameter" +template <class T, class R, class... P> +class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase { + struct Data { + T *instance; +#ifdef DEBUG_ENABLED + uint64_t object_id; #endif + R(T::*method) + (P...); + } data; -template <class T, class R, class... P, size_t... Is> -void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) { - r_error.error = Callable::CallError::CALL_OK; +public: + virtual ObjectID get_object() const { +#ifdef DEBUG_ENABLED + if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) { + return ObjectID(); + } +#endif + return data.instance->get_instance_id(); + } -#ifdef DEBUG_METHODS_ENABLED - r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); -#else - (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...); + virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr, "Invalid Object id '" + uitos(data.object_id) + "', can't call method."); #endif -} + call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error); + } -#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop + CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) { + zeromem(&data, sizeof(Data)); // Clear beforehand, may have padding bytes. + data.instance = p_instance; +#ifdef DEBUG_ENABLED + data.object_id = p_instance->get_instance_id(); #endif + data.method = p_method; + _setup((uint32_t *)&data, sizeof(Data)); + } +}; template <class T, class R, class... P> -void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { +Callable create_custom_callable_function_pointer(T *p_instance, #ifdef DEBUG_METHODS_ENABLED - if ((size_t)p_argcount > sizeof...(P)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = sizeof...(P); - return; - } - - if ((size_t)p_argcount < sizeof...(P)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = sizeof...(P); - return; - } + const char *p_func_text, #endif - call_with_variant_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); + R (T::*p_method)(P...)) { + typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise. + CCMP *ccmp = memnew(CCMP(p_instance, p_method)); +#ifdef DEBUG_METHODS_ENABLED + ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand. +#endif + return Callable(ccmp); } +// CONST VERSION WITH RETURN + template <class T, class R, class... P> -class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase { +class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase { struct Data { T *instance; #ifdef DEBUG_ENABLED uint64_t object_id; #endif R(T::*method) - (P...); + (P...) const; } data; public: @@ -279,10 +204,10 @@ public: #ifdef DEBUG_ENABLED ERR_FAIL_COND_MSG(ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr, "Invalid Object id '" + uitos(data.object_id) + "', can't call method."); #endif - call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error); + call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error); } - CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) { + CallableCustomMethodPointerRetC(T *p_instance, R (T::*p_method)(P...) const) { zeromem(&data, sizeof(Data)); // Clear beforehand, may have padding bytes. data.instance = p_instance; #ifdef DEBUG_ENABLED @@ -298,9 +223,8 @@ Callable create_custom_callable_function_pointer(T *p_instance, #ifdef DEBUG_METHODS_ENABLED const char *p_func_text, #endif - R (T::*p_method)(P...)) { - - typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise. + R (T::*p_method)(P...) const) { + typedef CallableCustomMethodPointerRetC<T, R, P...> CCMP; // Messes with memnew otherwise. CCMP *ccmp = memnew(CCMP(p_instance, p_method)); #ifdef DEBUG_METHODS_ENABLED ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand. diff --git a/core/class_db.cpp b/core/object/class_db.cpp index 88f1df3457..6bc6d653d1 100644 --- a/core/class_db.cpp +++ b/core/object/class_db.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "class_db.h" -#include "core/engine.h" +#include "core/config/engine.h" #include "core/os/mutex.h" #include "core/version.h" @@ -242,21 +242,28 @@ HashMap<StringName, ClassDB::ClassInfo> ClassDB::classes; HashMap<StringName, StringName> ClassDB::resource_base_extensions; HashMap<StringName, StringName> ClassDB::compat_classes; -bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) { - OBJTYPE_RLOCK; +bool ClassDB::_is_parent_class(const StringName &p_class, const StringName &p_inherits) { + if (!classes.has(p_class)) { + return false; + } StringName inherits = p_class; - while (inherits.operator String().length()) { if (inherits == p_inherits) { return true; } - inherits = get_parent_class(inherits); + inherits = _get_parent_class(inherits); } return false; } +bool ClassDB::is_parent_class(const StringName &p_class, const StringName &p_inherits) { + OBJTYPE_RLOCK; + + return _is_parent_class(p_class, p_inherits); +} + void ClassDB::get_class_list(List<StringName> *p_classes) { OBJTYPE_RLOCK; @@ -275,7 +282,7 @@ void ClassDB::get_inheriters_from_class(const StringName &p_class, List<StringNa const StringName *k = nullptr; while ((k = classes.next(k))) { - if (*k != p_class && is_parent_class(*k, p_class)) { + if (*k != p_class && _is_parent_class(*k, p_class)) { p_classes->push_back(*k); } } @@ -287,7 +294,7 @@ void ClassDB::get_direct_inheriters_from_class(const StringName &p_class, List<S const StringName *k = nullptr; while ((k = classes.next(k))) { - if (*k != p_class && get_parent_class(*k) == p_class) { + if (*k != p_class && _get_parent_class(*k) == p_class) { p_classes->push_back(*k); } } @@ -315,14 +322,18 @@ StringName ClassDB::get_compatibility_remapped_class(const StringName &p_class) return p_class; } -StringName ClassDB::get_parent_class(const StringName &p_class) { - OBJTYPE_RLOCK; - +StringName ClassDB::_get_parent_class(const StringName &p_class) { ClassInfo *ti = classes.getptr(p_class); ERR_FAIL_COND_V_MSG(!ti, StringName(), "Cannot get class '" + String(p_class) + "'."); return ti->inherits; } +StringName ClassDB::get_parent_class(const StringName &p_class) { + OBJTYPE_RLOCK; + + return _get_parent_class(p_class); +} + ClassDB::APIType ClassDB::get_api_type(const StringName &p_class) { OBJTYPE_RLOCK; @@ -366,7 +377,7 @@ uint64_t ClassDB::get_api_hash(APIType p_api) { while ((k = t->method_map.next(k))) { String name = k->operator String(); - ERR_CONTINUE(name.empty()); + ERR_CONTINUE(name.is_empty()); if (name[0] == '_') { continue; // Ignore non-virtual methods that start with an underscore @@ -970,6 +981,7 @@ void ClassDB::add_property_subgroup(StringName p_class, const String &p_name, co type->property_list.push_back(PropertyInfo(Variant::NIL, p_name, PROPERTY_HINT_NONE, p_prefix, PROPERTY_USAGE_SUBGROUP)); } +// NOTE: For implementation simplicity reasons, this method doesn't allow setters to have optional arguments at the end. void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, const StringName &p_setter, const StringName &p_getter, int p_index) { lock->read_lock(); ClassInfo *type = classes.getptr(p_class); @@ -1343,7 +1355,7 @@ MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const c defvals.resize(p_defcount); for (int i = 0; i < p_defcount; i++) { - defvals.write[i] = *p_defs[p_defcount - i - 1]; + defvals.write[i] = *p_defs[i]; } p_bind->set_default_arguments(defvals); diff --git a/core/class_db.h b/core/object/class_db.h index 86ac2aa001..0591676b92 100644 --- a/core/class_db.h +++ b/core/object/class_db.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,17 +31,17 @@ #ifndef CLASS_DB_H #define CLASS_DB_H -#include "core/method_bind.h" -#include "core/object.h" -#include "core/print_string.h" +#include "core/object/method_bind.h" +#include "core/object/object.h" +#include "core/string/print_string.h" /** To bind more then 6 parameters include this: - * #include "core/method_bind_ext.gen.inc" + * */ // Makes callable_mp readily available in all classes connecting signals. // Needs to come after method_bind and object have been included. -#include "core/callable_method_pointer.h" +#include "core/object/callable_method_pointer.h" #define DEFVAL(m_defval) (m_defval) @@ -164,6 +164,11 @@ public: static HashMap<StringName, HashMap<StringName, Variant>> default_values; static Set<StringName> default_values_cached; +private: + // Non-locking variants of get_parent_class and is_parent_class. + static StringName _get_parent_class(const StringName &p_class); + static bool _is_parent_class(const StringName &p_class, const StringName &p_inherits); + public: // DO NOT USE THIS!!!!!! NEEDS TO BE PUBLIC BUT DO NOT USE NO MATTER WHAT!!! template <class T> diff --git a/core/message_queue.cpp b/core/object/message_queue.cpp index 6dcf24e7ed..4751c69f1e 100644 --- a/core/message_queue.cpp +++ b/core/object/message_queue.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,9 @@ #include "message_queue.h" +#include "core/config/project_settings.h" #include "core/core_string_names.h" -#include "core/project_settings.h" -#include "core/script_language.h" +#include "core/object/script_language.h" MessageQueue *MessageQueue::singleton = nullptr; diff --git a/core/message_queue.h b/core/object/message_queue.h index 710a605371..1b8def62d3 100644 --- a/core/message_queue.h +++ b/core/object/message_queue.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef MESSAGE_QUEUE_H #define MESSAGE_QUEUE_H -#include "core/object.h" +#include "core/object/class_db.h" #include "core/os/thread_safe.h" class MessageQueue { diff --git a/core/method_bind.cpp b/core/object/method_bind.cpp index 3244c63292..9c5ed60708 100644 --- a/core/method_bind.cpp +++ b/core/object/method_bind.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ // object.h needs to be the first include *before* method_bind.h // FIXME: Find out why and fix potential cyclical dependencies. -#include "core/object.h" +#include "core/object/object.h" #include "method_bind.h" diff --git a/core/object/method_bind.h b/core/object/method_bind.h new file mode 100644 index 0000000000..7cf4f8d4e8 --- /dev/null +++ b/core/object/method_bind.h @@ -0,0 +1,577 @@ +/*************************************************************************/ +/* method_bind.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef METHOD_BIND_H +#define METHOD_BIND_H + +#include "core/variant/binder_common.h" + +enum MethodFlags { + METHOD_FLAG_NORMAL = 1, + METHOD_FLAG_EDITOR = 2, + METHOD_FLAG_NOSCRIPT = 4, + METHOD_FLAG_CONST = 8, + METHOD_FLAG_REVERSE = 16, // used for events + METHOD_FLAG_VIRTUAL = 32, + METHOD_FLAG_FROM_SCRIPT = 64, + METHOD_FLAG_VARARG = 128, + METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL, +}; + +VARIANT_ENUM_CAST(MethodFlags) + +// some helpers + +class MethodBind { + int method_id; + uint32_t hint_flags = METHOD_FLAGS_DEFAULT; + StringName name; + StringName instance_class; + Vector<Variant> default_arguments; + int default_argument_count = 0; + int argument_count = 0; + + bool _const = false; + bool _returns = false; + +protected: +#ifdef DEBUG_METHODS_ENABLED + Variant::Type *argument_types = nullptr; + Vector<StringName> arg_names; +#endif + void _set_const(bool p_const); + void _set_returns(bool p_returns); +#ifdef DEBUG_METHODS_ENABLED + virtual Variant::Type _gen_argument_type(int p_arg) const = 0; + virtual PropertyInfo _gen_argument_type_info(int p_arg) const = 0; + void _generate_argument_types(int p_count); + +#endif + void set_argument_count(int p_count) { argument_count = p_count; } + +public: + _FORCE_INLINE_ const Vector<Variant> &get_default_arguments() const { return default_arguments; } + _FORCE_INLINE_ int get_default_argument_count() const { return default_argument_count; } + + _FORCE_INLINE_ Variant has_default_argument(int p_arg) const { + int idx = p_arg - (argument_count - default_arguments.size()); + + if (idx < 0 || idx >= default_arguments.size()) { + return false; + } else { + return true; + } + } + + _FORCE_INLINE_ Variant get_default_argument(int p_arg) const { + int idx = p_arg - (argument_count - default_arguments.size()); + + if (idx < 0 || idx >= default_arguments.size()) { + return Variant(); + } else { + return default_arguments[idx]; + } + } + +#ifdef DEBUG_METHODS_ENABLED + _FORCE_INLINE_ Variant::Type get_argument_type(int p_argument) const { + ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, Variant::NIL); + return argument_types[p_argument + 1]; + } + + PropertyInfo get_argument_info(int p_argument) const; + PropertyInfo get_return_info() const; + + void set_argument_names(const Vector<StringName> &p_names); // Set by ClassDB, can't be inferred otherwise. + Vector<StringName> get_argument_names() const; + + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const = 0; +#endif + + void set_hint_flags(uint32_t p_hint) { hint_flags = p_hint; } + uint32_t get_hint_flags() const { return hint_flags | (is_const() ? METHOD_FLAG_CONST : 0) | (is_vararg() ? METHOD_FLAG_VARARG : 0); } + _FORCE_INLINE_ StringName get_instance_class() const { return instance_class; } + _FORCE_INLINE_ void set_instance_class(const StringName &p_class) { instance_class = p_class; } + + _FORCE_INLINE_ int get_argument_count() const { return argument_count; }; + + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) = 0; + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) = 0; + + StringName get_name() const; + void set_name(const StringName &p_name); + _FORCE_INLINE_ int get_method_id() const { return method_id; } + _FORCE_INLINE_ bool is_const() const { return _const; } + _FORCE_INLINE_ bool has_return() const { return _returns; } + virtual bool is_vararg() const { return false; } + + void set_default_arguments(const Vector<Variant> &p_defargs); + + MethodBind(); + virtual ~MethodBind(); +}; + +template <class T> +class MethodBindVarArg : public MethodBind { +public: + typedef Variant (T::*NativeCall)(const Variant **, int, Callable::CallError &); + +protected: + NativeCall call_method = nullptr; +#ifdef DEBUG_METHODS_ENABLED + MethodInfo arguments; +#endif + +public: +#ifdef DEBUG_METHODS_ENABLED + virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + if (p_arg < 0) { + return arguments.return_val; + } else if (p_arg < arguments.arguments.size()) { + return arguments.arguments[p_arg]; + } else { + return PropertyInfo(Variant::NIL, "arg_" + itos(p_arg), PROPERTY_HINT_NONE, String(), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT); + } + } + + virtual Variant::Type _gen_argument_type(int p_arg) const { + return _gen_argument_type_info(p_arg).type; + } + + virtual GodotTypeInfo::Metadata get_argument_meta(int) const { + return GodotTypeInfo::METADATA_NONE; + } +#else + virtual Variant::Type _gen_argument_type(int p_arg) const { + return Variant::NIL; + } +#endif + + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + T *instance = static_cast<T *>(p_object); + return (instance->*call_method)(p_args, p_arg_count, r_error); + } + + void set_method_info(const MethodInfo &p_info, bool p_return_nil_is_variant) { + set_argument_count(p_info.arguments.size()); +#ifdef DEBUG_METHODS_ENABLED + Variant::Type *at = memnew_arr(Variant::Type, p_info.arguments.size() + 1); + at[0] = p_info.return_val.type; + if (p_info.arguments.size()) { + Vector<StringName> names; + names.resize(p_info.arguments.size()); + for (int i = 0; i < p_info.arguments.size(); i++) { + at[i + 1] = p_info.arguments[i].type; + names.write[i] = p_info.arguments[i].name; + } + + set_argument_names(names); + } + argument_types = at; + arguments = p_info; + if (p_return_nil_is_variant) { + arguments.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; + } +#endif + } + + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { + ERR_FAIL(); // Can't call. + } + + void set_method(NativeCall p_method) { call_method = p_method; } + virtual bool is_const() const { return false; } + + virtual bool is_vararg() const { return true; } + + MethodBindVarArg() { + _set_returns(true); + } +}; + +template <class T> +MethodBind *create_vararg_method_bind(Variant (T::*p_method)(const Variant **, int, Callable::CallError &), const MethodInfo &p_info, bool p_return_nil_is_variant) { + MethodBindVarArg<T> *a = memnew((MethodBindVarArg<T>)); + a->set_method(p_method); + a->set_method_info(p_info, p_return_nil_is_variant); + a->set_instance_class(T::get_class_static()); + return a; +} + +/**** VARIADIC TEMPLATES ****/ + +#ifndef TYPED_METHOD_BIND +class __UnexistingClass; +#define MB_T __UnexistingClass +#else +#define MB_T T +#endif + +// no return, not const +#ifdef TYPED_METHOD_BIND +template <class T, class... P> +#else +template <class... P> +#endif +class MethodBindT : public MethodBind { + void (MB_T::*method)(P...); + +protected: +#ifdef DEBUG_METHODS_ENABLED +// GCC raises warnings in the case P = {} as the comparison is always false... +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wlogical-op" +#endif + virtual Variant::Type _gen_argument_type(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + return call_get_argument_type<P...>(p_arg); + } else { + return Variant::NIL; + } + } +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + + virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + PropertyInfo pi; + call_get_argument_type_info<P...>(p_arg, pi); + return pi; + } +#endif + +public: +#ifdef DEBUG_METHODS_ENABLED + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + return call_get_argument_metadata<P...>(p_arg); + } + +#endif + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +#ifdef TYPED_METHOD_BIND + call_with_variant_args_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); +#else + call_with_variant_args_dv((MB_T *)(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); +#endif + return Variant(); + } + + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { +#ifdef TYPED_METHOD_BIND + call_with_ptr_args<T, P...>(static_cast<T *>(p_object), method, p_args); +#else + call_with_ptr_args<MB_T, P...>((MB_T *)(p_object), method, p_args); +#endif + } + + MethodBindT(void (MB_T::*p_method)(P...)) { + method = p_method; +#ifdef DEBUG_METHODS_ENABLED + _generate_argument_types(sizeof...(P)); +#endif + set_argument_count(sizeof...(P)); + } +}; + +template <class T, class... P> +MethodBind *create_method_bind(void (T::*p_method)(P...)) { +#ifdef TYPED_METHOD_BIND + MethodBind *a = memnew((MethodBindT<T, P...>)(p_method)); +#else + MethodBind *a = memnew((MethodBindT<P...>)(reinterpret_cast<void (MB_T::*)(P...)>(p_method))); +#endif + a->set_instance_class(T::get_class_static()); + return a; +} + +// no return, not const + +#ifdef TYPED_METHOD_BIND +template <class T, class... P> +#else +template <class... P> +#endif +class MethodBindTC : public MethodBind { + void (MB_T::*method)(P...) const; + +protected: +#ifdef DEBUG_METHODS_ENABLED +// GCC raises warnings in the case P = {} as the comparison is always false... +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wlogical-op" +#endif + virtual Variant::Type _gen_argument_type(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + return call_get_argument_type<P...>(p_arg); + } else { + return Variant::NIL; + } + } +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + + virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + PropertyInfo pi; + call_get_argument_type_info<P...>(p_arg, pi); + return pi; + } +#endif + +public: +#ifdef DEBUG_METHODS_ENABLED + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + return call_get_argument_metadata<P...>(p_arg); + } + +#endif + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { +#ifdef TYPED_METHOD_BIND + call_with_variant_argsc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); +#else + call_with_variant_argsc_dv((MB_T *)(p_object), method, p_args, p_arg_count, r_error, get_default_arguments()); +#endif + return Variant(); + } + + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { +#ifdef TYPED_METHOD_BIND + call_with_ptr_argsc<T, P...>(static_cast<T *>(p_object), method, p_args); +#else + call_with_ptr_argsc<MB_T, P...>((MB_T *)(p_object), method, p_args); +#endif + } + + MethodBindTC(void (MB_T::*p_method)(P...) const) { + method = p_method; + _set_const(true); +#ifdef DEBUG_METHODS_ENABLED + _generate_argument_types(sizeof...(P)); +#endif + set_argument_count(sizeof...(P)); + } +}; + +template <class T, class... P> +MethodBind *create_method_bind(void (T::*p_method)(P...) const) { +#ifdef TYPED_METHOD_BIND + MethodBind *a = memnew((MethodBindTC<T, P...>)(p_method)); +#else + MethodBind *a = memnew((MethodBindTC<P...>)(reinterpret_cast<void (MB_T::*)(P...) const>(p_method))); +#endif + a->set_instance_class(T::get_class_static()); + return a; +} + +// return, not const + +#ifdef TYPED_METHOD_BIND +template <class T, class R, class... P> +#else +template <class R, class... P> +#endif +class MethodBindTR : public MethodBind { + R(MB_T::*method) + (P...); + +protected: +#ifdef DEBUG_METHODS_ENABLED +// GCC raises warnings in the case P = {} as the comparison is always false... +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wlogical-op" +#endif + virtual Variant::Type _gen_argument_type(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + return call_get_argument_type<P...>(p_arg); + } else { + return GetTypeInfo<R>::VARIANT_TYPE; + } + } + + virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + PropertyInfo pi; + call_get_argument_type_info<P...>(p_arg, pi); + return pi; + } else { + return GetTypeInfo<R>::get_class_info(); + } + } +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif +#endif + +public: +#ifdef DEBUG_METHODS_ENABLED + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + if (p_arg >= 0) { + return call_get_argument_metadata<P...>(p_arg); + } else { + return GetTypeInfo<R>::METADATA; + } + } +#endif + + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + Variant ret; +#ifdef TYPED_METHOD_BIND + call_with_variant_args_ret_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); +#else + call_with_variant_args_ret_dv((MB_T *)p_object, method, p_args, p_arg_count, ret, r_error, get_default_arguments()); +#endif + return ret; + } + + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { +#ifdef TYPED_METHOD_BIND + call_with_ptr_args_ret<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret); +#else + call_with_ptr_args_ret<MB_T, R, P...>((MB_T *)(p_object), method, p_args, r_ret); +#endif + } + + MethodBindTR(R (MB_T::*p_method)(P...)) { + method = p_method; + _set_returns(true); +#ifdef DEBUG_METHODS_ENABLED + _generate_argument_types(sizeof...(P)); +#endif + set_argument_count(sizeof...(P)); + } +}; + +template <class T, class R, class... P> +MethodBind *create_method_bind(R (T::*p_method)(P...)) { +#ifdef TYPED_METHOD_BIND + MethodBind *a = memnew((MethodBindTR<T, R, P...>)(p_method)); +#else + MethodBind *a = memnew((MethodBindTR<R, P...>)(reinterpret_cast<R (MB_T::*)(P...)>(p_method))); +#endif + + a->set_instance_class(T::get_class_static()); + return a; +} + +// return, const + +#ifdef TYPED_METHOD_BIND +template <class T, class R, class... P> +#else +template <class R, class... P> +#endif +class MethodBindTRC : public MethodBind { + R(MB_T::*method) + (P...) const; + +protected: +#ifdef DEBUG_METHODS_ENABLED +// GCC raises warnings in the case P = {} as the comparison is always false... +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wlogical-op" +#endif + virtual Variant::Type _gen_argument_type(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + return call_get_argument_type<P...>(p_arg); + } else { + return GetTypeInfo<R>::VARIANT_TYPE; + } + } + + virtual PropertyInfo _gen_argument_type_info(int p_arg) const { + if (p_arg >= 0 && p_arg < (int)sizeof...(P)) { + PropertyInfo pi; + call_get_argument_type_info<P...>(p_arg, pi); + return pi; + } else { + return GetTypeInfo<R>::get_class_info(); + } + } +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif +#endif + +public: +#ifdef DEBUG_METHODS_ENABLED + virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const { + if (p_arg >= 0) { + return call_get_argument_metadata<P...>(p_arg); + } else { + return GetTypeInfo<R>::METADATA; + } + } +#endif + + virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + Variant ret; +#ifdef TYPED_METHOD_BIND + call_with_variant_args_retc_dv(static_cast<T *>(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); +#else + call_with_variant_args_retc_dv((MB_T *)(p_object), method, p_args, p_arg_count, ret, r_error, get_default_arguments()); +#endif + return ret; + } + + virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) { +#ifdef TYPED_METHOD_BIND + call_with_ptr_args_retc<T, R, P...>(static_cast<T *>(p_object), method, p_args, r_ret); +#else + call_with_ptr_args_retc<MB_T, R, P...>((MB_T *)(p_object), method, p_args, r_ret); +#endif + } + + MethodBindTRC(R (MB_T::*p_method)(P...) const) { + method = p_method; + _set_returns(true); + _set_const(true); +#ifdef DEBUG_METHODS_ENABLED + _generate_argument_types(sizeof...(P)); +#endif + set_argument_count(sizeof...(P)); + } +}; + +template <class T, class R, class... P> +MethodBind *create_method_bind(R (T::*p_method)(P...) const) { +#ifdef TYPED_METHOD_BIND + MethodBind *a = memnew((MethodBindTRC<T, R, P...>)(p_method)); +#else + MethodBind *a = memnew((MethodBindTRC<R, P...>)(reinterpret_cast<R (MB_T::*)(P...) const>(p_method))); +#endif + a->set_instance_class(T::get_class_static()); + return a; +} + +#endif // METHOD_BIND_H diff --git a/core/object.cpp b/core/object/object.cpp index 0d9e5c5116..171bc4dc2c 100644 --- a/core/object.cpp +++ b/core/object/object.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,14 +30,14 @@ #include "object.h" -#include "core/class_db.h" #include "core/core_string_names.h" -#include "core/message_queue.h" +#include "core/io/resource.h" +#include "core/object/class_db.h" +#include "core/object/message_queue.h" +#include "core/object/script_language.h" #include "core/os/os.h" -#include "core/print_string.h" -#include "core/resource.h" -#include "core/script_language.h" -#include "core/translation.h" +#include "core/string/print_string.h" +#include "core/string/translation.h" #ifdef DEBUG_ENABLED @@ -421,17 +421,6 @@ void Object::set(const StringName &p_name, const Variant &p_value, bool *r_valid return; } - { - bool valid; - setvar(p_name, p_value, &valid); - if (valid) { - if (r_valid) { - *r_valid = true; - } - return; - } - } - #ifdef TOOLS_ENABLED if (script_instance) { bool valid; @@ -496,18 +485,6 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const { return ret; } - //if nothing else, use getvar - { - bool valid; - ret = getvar(p_name, &valid); - if (valid) { - if (r_valid) { - *r_valid = true; - } - return ret; - } - } - #ifdef TOOLS_ENABLED if (script_instance) { bool valid; @@ -529,7 +506,7 @@ Variant Object::get(const StringName &p_name, bool *r_valid) const { } void Object::set_indexed(const Vector<StringName> &p_names, const Variant &p_value, bool *r_valid) { - if (p_names.empty()) { + if (p_names.is_empty()) { if (r_valid) { *r_valid = false; } @@ -555,9 +532,12 @@ void Object::set_indexed(const Vector<StringName> &p_names, const Variant &p_val } for (int i = 1; i < p_names.size() - 1; i++) { - value_stack.push_back(value_stack.back()->get().get_named(p_names[i], r_valid)); + value_stack.push_back(value_stack.back()->get().get_named(p_names[i], valid)); + if (r_valid) { + *r_valid = valid; + } - if (!*r_valid) { + if (!valid) { value_stack.clear(); return; } @@ -566,10 +546,13 @@ void Object::set_indexed(const Vector<StringName> &p_names, const Variant &p_val value_stack.push_back(p_value); // p_names[p_names.size() - 1] for (int i = p_names.size() - 1; i > 0; i--) { - value_stack.back()->prev()->get().set_named(p_names[i], value_stack.back()->get(), r_valid); + value_stack.back()->prev()->get().set_named(p_names[i], value_stack.back()->get(), valid); value_stack.pop_back(); - if (!*r_valid) { + if (r_valid) { + *r_valid = valid; + } + if (!valid) { value_stack.clear(); return; } @@ -578,11 +561,11 @@ void Object::set_indexed(const Vector<StringName> &p_names, const Variant &p_val set(p_names[0], value_stack.back()->get(), r_valid); value_stack.pop_back(); - ERR_FAIL_COND(!value_stack.empty()); + ERR_FAIL_COND(!value_stack.is_empty()); } Variant Object::get_indexed(const Vector<StringName> &p_names, bool *r_valid) const { - if (p_names.empty()) { + if (p_names.is_empty()) { if (r_valid) { *r_valid = false; } @@ -592,7 +575,7 @@ Variant Object::get_indexed(const Vector<StringName> &p_names, bool *r_valid) co Variant current_value = get(p_names[0], &valid); for (int i = 1; i < p_names.size(); i++) { - current_value = current_value.get_named(p_names[i], &valid); + current_value = current_value.get_named(p_names[i], valid); if (!valid) { break; @@ -614,12 +597,9 @@ void Object::get_property_list(List<PropertyInfo> *p_list, bool p_reversed) cons _get_property_listv(p_list, p_reversed); if (!is_class("Script")) { // can still be set, but this is for userfriendlyness -#ifdef TOOLS_ENABLED - p_list->push_back(PropertyInfo(Variant::NIL, "Script", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP)); -#endif p_list->push_back(PropertyInfo(Variant::OBJECT, "script", PROPERTY_HINT_RESOURCE_TYPE, "Script", PROPERTY_USAGE_DEFAULT)); } - if (!metadata.empty()) { + if (!metadata.is_empty()) { p_list->push_back(PropertyInfo(Variant::DICTIONARY, "__meta__", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); } if (script_instance && !p_reversed) { @@ -698,6 +678,10 @@ Variant Object::getvar(const Variant &p_key, bool *r_valid) const { if (r_valid) { *r_valid = false; } + + if (p_key.get_type() == Variant::STRING_NAME || p_key.get_type() == Variant::STRING) { + return get(p_key, r_valid); + } return Variant(); } @@ -705,6 +689,9 @@ void Object::setvar(const Variant &p_key, const Variant &p_value, bool *r_valid) if (r_valid) { *r_valid = false; } + if (p_key.get_type() == Variant::STRING_NAME || p_key.get_type() == Variant::STRING) { + return set(p_key, p_value, r_valid); + } } Variant Object::callv(const StringName &p_method, const Array &p_args) { @@ -836,10 +823,6 @@ void Object::property_list_changed_notify() { _change_notify(); } -void Object::cancel_delete() { - _predelete_ok = true; -} - void Object::set_script_and_instance(const Variant &p_script, ScriptInstance *p_instance) { //this function is not meant to be used in any of these ways ERR_FAIL_COND(p_script.is_null()); @@ -1106,7 +1089,7 @@ Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int } } - while (!disconnect_data.empty()) { + while (!disconnect_data.is_empty()) { const _ObjectSignalDisconnectData &dd = disconnect_data.front()->get(); _disconnect(dd.signal, dd.callable); @@ -1279,10 +1262,6 @@ void Object::get_signals_connected_to_this(List<Connection> *p_connections) cons } } -Error Object::connect_compat(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, const Vector<Variant> &p_binds, uint32_t p_flags) { - return connect(p_signal, Callable(p_to_object, p_to_method), p_binds, p_flags); -} - Error Object::connect(const StringName &p_signal, const Callable &p_callable, const Vector<Variant> &p_binds, uint32_t p_flags) { ERR_FAIL_COND_V(p_callable.is_null(), ERR_INVALID_PARAMETER); @@ -1344,10 +1323,6 @@ Error Object::connect(const StringName &p_signal, const Callable &p_callable, co return OK; } -bool Object::is_connected_compat(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) const { - return is_connected(p_signal, Callable(p_to_object, p_to_method)); -} - bool Object::is_connected(const StringName &p_signal, const Callable &p_callable) const { ERR_FAIL_COND_V(p_callable.is_null(), false); const SignalData *s = signal_map.getptr(p_signal); @@ -1371,10 +1346,6 @@ bool Object::is_connected(const StringName &p_signal, const Callable &p_callable //return (E!=nullptr ); } -void Object::disconnect_compat(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) { - _disconnect(p_signal, Callable(p_to_object, p_to_method)); -} - void Object::disconnect(const StringName &p_signal, const Callable &p_callable) { _disconnect(p_signal, p_callable); } @@ -1386,7 +1357,12 @@ void Object::_disconnect(const StringName &p_signal, const Callable &p_callable, ERR_FAIL_COND(!target_object); SignalData *s = signal_map.getptr(p_signal); - ERR_FAIL_COND_MSG(!s, vformat("Nonexistent signal '%s' in %s.", p_signal, to_string())); + if (!s) { + bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal) || + (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal)); + ERR_FAIL_COND_MSG(signal_is_valid, "Attempt to disconnect a nonexistent connection from '" + to_string() + "'. signal: '" + p_signal + "', callable: '" + p_callable + "'."); + } + ERR_FAIL_COND_MSG(!s, vformat("Disconnecting nonexistent signal '%s' in %s.", p_signal, to_string())); ERR_FAIL_COND_MSG(!s->slot_map.has(*p_callable.get_base_comparator()), "Disconnecting nonexistent signal '" + p_signal + "', callable: " + p_callable + "."); @@ -1402,7 +1378,7 @@ void Object::_disconnect(const StringName &p_signal, const Callable &p_callable, target_object->connections.erase(slot->cE); s->slot_map.erase(*p_callable.get_base_comparator()); - if (s->slot_map.empty() && ClassDB::has_signal(get_class_name(), p_signal)) { + if (s->slot_map.is_empty() && ClassDB::has_signal(get_class_name(), p_signal)) { //not user signal, delete signal_map.erase(p_signal); } @@ -1700,7 +1676,8 @@ Variant::Type Object::get_static_property_type_indexed(const Vector<StringName> } Callable::CallError ce; - Variant check = Variant::construct(t, nullptr, 0, ce); + Variant check; + Variant::construct(t, check, nullptr, 0, ce); for (int i = 1; i < p_path.size(); i++) { if (check.get_type() == Variant::OBJECT || check.get_type() == Variant::DICTIONARY || check.get_type() == Variant::ARRAY) { @@ -1711,7 +1688,7 @@ Variant::Type Object::get_static_property_type_indexed(const Vector<StringName> return Variant::NIL; } - check = check.get_named(p_path[i], &valid); + check = check.get_named(p_path[i], valid); if (!valid) { if (r_valid) { @@ -1853,9 +1830,13 @@ void postinitialize_handler(Object *p_object) { void ObjectDB::debug_objects(DebugFunc p_func) { spin_lock.lock(); - for (uint32_t i = 0; i < slot_count; i++) { - uint32_t slot = object_slots[i].next_free; - p_func(object_slots[slot].object); + + for (uint32_t i = 0, count = slot_count; i < slot_max && count != 0; i++) { + if (object_slots[i].validator) { + p_func(object_slots[i].object); + + count--; + } } spin_lock.unlock(); } @@ -1967,20 +1948,23 @@ void ObjectDB::cleanup() { MethodBind *resource_get_path = ClassDB::get_method("Resource", "get_path"); Callable::CallError call_error; - for (uint32_t i = 0; i < slot_count; i++) { - uint32_t slot = object_slots[i].next_free; - Object *obj = object_slots[slot].object; + for (uint32_t i = 0, count = slot_count; i < slot_max && count != 0; i++) { + if (object_slots[i].validator) { + Object *obj = object_slots[i].object; - String extra_info; - if (obj->is_class("Node")) { - extra_info = " - Node name: " + String(node_get_name->call(obj, nullptr, 0, call_error)); - } - if (obj->is_class("Resource")) { - extra_info = " - Resource path: " + String(resource_get_path->call(obj, nullptr, 0, call_error)); - } + String extra_info; + if (obj->is_class("Node")) { + extra_info = " - Node name: " + String(node_get_name->call(obj, nullptr, 0, call_error)); + } + if (obj->is_class("Resource")) { + extra_info = " - Resource path: " + String(resource_get_path->call(obj, nullptr, 0, call_error)); + } - uint64_t id = uint64_t(slot) | (uint64_t(object_slots[slot].validator) << OBJECTDB_VALIDATOR_BITS) | (object_slots[slot].is_reference ? OBJECTDB_REFERENCE_BIT : 0); - print_line("Leaked instance: " + String(obj->get_class()) + ":" + itos(id) + extra_info); + uint64_t id = uint64_t(i) | (uint64_t(object_slots[i].validator) << OBJECTDB_VALIDATOR_BITS) | (object_slots[i].is_reference ? OBJECTDB_REFERENCE_BIT : 0); + print_line("Leaked instance: " + String(obj->get_class()) + ":" + itos(id) + extra_info); + + count--; + } } print_line("Hint: Leaked instances typically happen when nodes are removed from the scene tree (with `remove_child()`) but not freed (with `free()` or `queue_free()`)."); } diff --git a/core/object.h b/core/object/object.h index f600e597ec..7e460462cf 100644 --- a/core/object.h +++ b/core/object/object.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,16 +31,16 @@ #ifndef OBJECT_H #define OBJECT_H -#include "core/callable_bind.h" -#include "core/hash_map.h" -#include "core/list.h" -#include "core/map.h" -#include "core/object_id.h" +#include "core/object/object_id.h" #include "core/os/rw_lock.h" -#include "core/set.h" -#include "core/spin_lock.h" -#include "core/variant.h" -#include "core/vmap.h" +#include "core/os/spin_lock.h" +#include "core/templates/hash_map.h" +#include "core/templates/list.h" +#include "core/templates/map.h" +#include "core/templates/set.h" +#include "core/templates/vmap.h" +#include "core/variant/callable_bind.h" +#include "core/variant/variant.h" #define VARIANT_ARG_LIST const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant() #define VARIANT_ARG_PASS p_arg1, p_arg2, p_arg3, p_arg4, p_arg5 @@ -98,7 +98,6 @@ enum PropertyHint { }; enum PropertyUsageFlags { - PROPERTY_USAGE_STORAGE = 1, PROPERTY_USAGE_EDITOR = 2, PROPERTY_USAGE_NETWORK = 4, @@ -406,7 +405,6 @@ class ScriptInstance; class Object { public: enum ConnectFlags { - CONNECT_DEFERRED = 1, CONNECT_PERSIST = 2, // hint for scene to save this connection CONNECT_ONESHOT = 4, @@ -484,8 +482,6 @@ private: void _set_indexed_bind(const NodePath &p_name, const Variant &p_value); Variant _get_indexed_bind(const NodePath &p_name) const; - void property_list_changed_notify(); - _FORCE_INLINE_ void _construct_object(bool p_reference); friend class Reference; @@ -527,8 +523,7 @@ protected: static void get_valid_parents_static(List<String> *p_parents); static void _get_valid_parents_static(List<String> *p_parents); - void cancel_delete(); - + void property_list_changed_notify(); virtual void _changed_callback(Object *p_changed, const char *p_prop); //Variant _call_bind(const StringName& p_name, const Variant& p_arg1 = Variant(), const Variant& p_arg2 = Variant(), const Variant& p_arg3 = Variant(), const Variant& p_arg4 = Variant()); @@ -699,10 +694,6 @@ public: int get_persistent_signal_connection_count() const; void get_signals_connected_to_this(List<Connection> *p_connections) const; - Error connect_compat(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, const Vector<Variant> &p_binds = Vector<Variant>(), uint32_t p_flags = 0); - void disconnect_compat(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method); - bool is_connected_compat(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method) const; - Error connect(const StringName &p_signal, const Callable &p_callable, const Vector<Variant> &p_binds = Vector<Variant>(), uint32_t p_flags = 0); void disconnect(const StringName &p_signal, const Callable &p_callable); bool is_connected(const StringName &p_signal, const Callable &p_callable) const; @@ -812,7 +803,4 @@ public: static int get_object_count(); }; -//needed by macros -#include "core/class_db.h" - #endif // OBJECT_H diff --git a/core/object_id.h b/core/object/object_id.h index 63b0c27af8..7f2496ad48 100644 --- a/core/object_id.h +++ b/core/object/object_id.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/reference.cpp b/core/object/reference.cpp index d1dba0d9bf..71a52a9ba5 100644 --- a/core/reference.cpp +++ b/core/object/reference.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "reference.h" -#include "core/script_language.h" +#include "core/object/script_language.h" bool Reference::init_ref() { if (reference()) { diff --git a/core/reference.h b/core/object/reference.h index f5794b0b67..d02cb12069 100644 --- a/core/reference.h +++ b/core/object/reference.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +31,8 @@ #ifndef REFERENCE_H #define REFERENCE_H -#include "core/class_db.h" -#include "core/object.h" -#include "core/safe_refcount.h" +#include "core/object/class_db.h" +#include "core/templates/safe_refcount.h" class Reference : public Object { GDCLASS(Reference, Object); @@ -253,8 +252,6 @@ public: WeakRef() {} }; -#ifdef PTRCALL_ENABLED - template <class T> struct PtrToArg<Ref<T>> { _FORCE_INLINE_ static Ref<T> convert(const void *p_ptr) { @@ -273,8 +270,6 @@ struct PtrToArg<const Ref<T> &> { } }; -#endif // PTRCALL_ENABLED - #ifdef DEBUG_METHODS_ENABLED template <class T> diff --git a/core/script_language.cpp b/core/object/script_language.cpp index d535c54dea..c3f109a147 100644 --- a/core/script_language.cpp +++ b/core/object/script_language.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,10 +30,10 @@ #include "script_language.h" +#include "core/config/project_settings.h" #include "core/core_string_names.h" #include "core/debugger/engine_debugger.h" #include "core/debugger/script_debugger.h" -#include "core/project_settings.h" #include <stdint.h> @@ -275,7 +275,7 @@ void ScriptServer::save_global_classes() { gcarr.push_back(d); } - if (gcarr.empty()) { + if (gcarr.is_empty()) { if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) { ProjectSettings::get_singleton()->clear("_global_script_classes"); } diff --git a/core/script_language.h b/core/object/script_language.h index aa7014ed3e..f9898ccd0c 100644 --- a/core/script_language.h +++ b/core/object/script_language.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,10 +31,11 @@ #ifndef SCRIPT_LANGUAGE_H #define SCRIPT_LANGUAGE_H +#include "core/doc_data.h" #include "core/io/multiplayer_api.h" -#include "core/map.h" -#include "core/pair.h" -#include "core/resource.h" +#include "core/io/resource.h" +#include "core/templates/map.h" +#include "core/templates/pair.h" class ScriptLanguage; @@ -57,7 +58,6 @@ struct SortNetData { class ScriptServer { enum { - MAX_LANGUAGES = 16 }; @@ -146,6 +146,10 @@ public: virtual void set_source_code(const String &p_code) = 0; virtual Error reload(bool p_keep_state = false) = 0; +#ifdef TOOLS_ENABLED + virtual const Vector<DocData::ClassDoc> &get_documentation() const = 0; +#endif // TOOLS_ENABLED + virtual bool has_method(const StringName &p_method) const = 0; virtual MethodInfo get_method_info(const StringName &p_method) const = 0; @@ -255,6 +259,7 @@ struct ScriptCodeCompletionOption { String insert_text; Color font_color; RES icon; + Variant default_value; ScriptCodeCompletionOption() {} @@ -269,8 +274,6 @@ class ScriptCodeCompletionCache { static ScriptCodeCompletionCache *singleton; public: - virtual RES get_cached_resource(const String &p_path) = 0; - static ScriptCodeCompletionCache *get_singleton() { return singleton; } ScriptCodeCompletionCache(); @@ -310,7 +313,8 @@ public: virtual Script *create_script() const = 0; virtual bool has_named_classes() const = 0; virtual bool supports_builtin_mode() const = 0; - virtual bool can_inherit_from_file() { return false; } + virtual bool supports_documentation() const { return false; } + virtual bool can_inherit_from_file() const { return false; } virtual int find_function(const String &p_function, const String &p_code) const = 0; virtual String make_function(const String &p_class, const String &p_name, const PackedStringArray &p_args) const = 0; virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; } diff --git a/core/undo_redo.cpp b/core/object/undo_redo.cpp index 1dcbb0cd6b..c699820e75 100644 --- a/core/undo_redo.cpp +++ b/core/object/undo_redo.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,6 +30,7 @@ #include "undo_redo.h" +#include "core/io/resource.h" #include "core/os/os.h" void UndoRedo::_discard_redo() { @@ -104,8 +105,8 @@ void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIA ERR_FAIL_COND((current_action + 1) >= actions.size()); Operation do_op; do_op.object = p_object->get_instance_id(); - if (Object::cast_to<Resource>(p_object)) { - do_op.resref = Ref<Resource>(Object::cast_to<Resource>(p_object)); + if (Object::cast_to<Reference>(p_object)) { + do_op.ref = Ref<Reference>(Object::cast_to<Reference>(p_object)); } do_op.type = Operation::TYPE_METHOD; @@ -130,8 +131,8 @@ void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VAR Operation undo_op; undo_op.object = p_object->get_instance_id(); - if (Object::cast_to<Resource>(p_object)) { - undo_op.resref = Ref<Resource>(Object::cast_to<Resource>(p_object)); + if (Object::cast_to<Reference>(p_object)) { + undo_op.ref = Ref<Reference>(Object::cast_to<Reference>(p_object)); } undo_op.type = Operation::TYPE_METHOD; @@ -149,8 +150,8 @@ void UndoRedo::add_do_property(Object *p_object, const StringName &p_property, c ERR_FAIL_COND((current_action + 1) >= actions.size()); Operation do_op; do_op.object = p_object->get_instance_id(); - if (Object::cast_to<Resource>(p_object)) { - do_op.resref = Ref<Resource>(Object::cast_to<Resource>(p_object)); + if (Object::cast_to<Reference>(p_object)) { + do_op.ref = Ref<Reference>(Object::cast_to<Reference>(p_object)); } do_op.type = Operation::TYPE_PROPERTY; @@ -171,8 +172,8 @@ void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property, Operation undo_op; undo_op.object = p_object->get_instance_id(); - if (Object::cast_to<Resource>(p_object)) { - undo_op.resref = Ref<Resource>(Object::cast_to<Resource>(p_object)); + if (Object::cast_to<Reference>(p_object)) { + undo_op.ref = Ref<Reference>(Object::cast_to<Reference>(p_object)); } undo_op.type = Operation::TYPE_PROPERTY; @@ -187,8 +188,8 @@ void UndoRedo::add_do_reference(Object *p_object) { ERR_FAIL_COND((current_action + 1) >= actions.size()); Operation do_op; do_op.object = p_object->get_instance_id(); - if (Object::cast_to<Resource>(p_object)) { - do_op.resref = Ref<Resource>(Object::cast_to<Resource>(p_object)); + if (Object::cast_to<Reference>(p_object)) { + do_op.ref = Ref<Reference>(Object::cast_to<Reference>(p_object)); } do_op.type = Operation::TYPE_REFERENCE; @@ -207,8 +208,8 @@ void UndoRedo::add_undo_reference(Object *p_object) { Operation undo_op; undo_op.object = p_object->get_instance_id(); - if (Object::cast_to<Resource>(p_object)) { - undo_op.resref = Ref<Resource>(Object::cast_to<Resource>(p_object)); + if (Object::cast_to<Reference>(p_object)) { + undo_op.ref = Ref<Reference>(Object::cast_to<Reference>(p_object)); } undo_op.type = Operation::TYPE_REFERENCE; diff --git a/core/undo_redo.h b/core/object/undo_redo.h index b46f7ff867..7b28b138c1 100644 --- a/core/undo_redo.h +++ b/core/object/undo_redo.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef UNDO_REDO_H #define UNDO_REDO_H -#include "core/object.h" -#include "core/resource.h" +#include "core/object/class_db.h" +#include "core/object/reference.h" class UndoRedo : public Object { GDCLASS(UndoRedo, Object); @@ -61,7 +61,7 @@ private: }; Type type; - Ref<Resource> resref; + Ref<Reference> ref; ObjectID object; StringName name; Variant args[VARIANT_ARG_MAX]; diff --git a/core/os/copymem.h b/core/os/copymem.h index 04ea3caeff..6fd559356c 100644 --- a/core/os/copymem.h +++ b/core/os/copymem.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp index 5e1cb8ea29..fb9da9fbed 100644 --- a/core/os/dir_access.cpp +++ b/core/os/dir_access.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,10 +30,10 @@ #include "dir_access.h" +#include "core/config/project_settings.h" #include "core/os/file_access.h" #include "core/os/memory.h" #include "core/os/os.h" -#include "core/project_settings.h" String DirAccess::_get_root_path() const { switch (_access_type) { diff --git a/core/os/dir_access.h b/core/os/dir_access.h index 6bce9a4c12..c49c4cc4b8 100644 --- a/core/os/dir_access.h +++ b/core/os/dir_access.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef DIR_ACCESS_H #define DIR_ACCESS_H +#include "core/string/ustring.h" #include "core/typedefs.h" -#include "core/ustring.h" //@ TODO, excellent candidate for THREAD_SAFE MACRO, should go through all these and add THREAD_SAFE where it applies class DirAccess { @@ -57,7 +57,6 @@ protected: String _get_root_string() const; String fix_path(String p_path) const; - bool next_is_dir; template <class T> static DirAccess *_create_builtin() { diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index 9dbb2952f7..5a3df88619 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,11 +30,11 @@ #include "file_access.h" +#include "core/config/project_settings.h" #include "core/crypto/crypto_core.h" #include "core/io/file_access_pack.h" #include "core/io/marshalls.h" #include "core/os/os.h" -#include "core/project_settings.h" FileAccess::CreateFunc FileAccess::create_func[ACCESS_MAX] = { nullptr, nullptr }; @@ -51,7 +51,7 @@ FileAccess *FileAccess::create(AccessType p_access) { } bool FileAccess::exists(const String &p_name) { - if (PackedData::get_singleton() && PackedData::get_singleton()->has_path(p_name)) { + if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_name)) { return true; } @@ -254,8 +254,8 @@ class CharBuffer { Vector<char> vector; char stack_buffer[256]; - char *buffer; - int capacity; + char *buffer = nullptr; + int capacity = 0; int written = 0; bool grow() { @@ -349,7 +349,7 @@ Vector<String> FileAccess::get_csv_line(const String &p_delim) const { strings.push_back(current); current = String(); } else if (c == '"') { - if (l[i + 1] == '"') { + if (l[i + 1] == '"' && in_quote) { s[0] = '"'; current += s; i++; @@ -456,7 +456,7 @@ void FileAccess::store_double(double p_dest) { } uint64_t FileAccess::get_modified_time(const String &p_file) { - if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) { + if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) { return 0; } @@ -469,7 +469,7 @@ uint64_t FileAccess::get_modified_time(const String &p_file) { } uint32_t FileAccess::get_unix_permissions(const String &p_file) { - if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && PackedData::get_singleton()->has_path(p_file)) { + if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) { return 0; } @@ -482,6 +482,10 @@ uint32_t FileAccess::get_unix_permissions(const String &p_file) { } Error FileAccess::set_unix_permissions(const String &p_file, uint32_t p_permissions) { + if (PackedData::get_singleton() && !PackedData::get_singleton()->is_disabled() && (PackedData::get_singleton()->has_path(p_file) || PackedData::get_singleton()->has_directory(p_file))) { + return ERR_UNAVAILABLE; + } + FileAccess *fa = create_for_path(p_file); ERR_FAIL_COND_V_MSG(!fa, ERR_CANT_CREATE, "Cannot create FileAccess for path '" + p_file + "'."); diff --git a/core/os/file_access.h b/core/os/file_access.h index 48b9ee4269..1c78204c1d 100644 --- a/core/os/file_access.h +++ b/core/os/file_access.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,8 +33,8 @@ #include "core/math/math_defs.h" #include "core/os/memory.h" +#include "core/string/ustring.h" #include "core/typedefs.h" -#include "core/ustring.h" /** * Multi-Platform abstraction for accessing to files. @@ -81,7 +81,6 @@ public: virtual void _set_access_type(AccessType p_access); enum ModeFlags { - READ = 1, WRITE = 2, READ_WRITE = 3, diff --git a/core/os/keyboard.cpp b/core/os/keyboard.cpp index d088151a6d..4b2cafd8fe 100644 --- a/core/os/keyboard.cpp +++ b/core/os/keyboard.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,7 +38,6 @@ struct _KeyCodeText { }; static const _KeyCodeText _keycodes[] = { - /* clang-format off */ {KEY_ESCAPE ,"Escape"}, {KEY_TAB ,"Tab"}, diff --git a/core/os/keyboard.h b/core/os/keyboard.h index 5d11e6a378..3ef70e786f 100644 --- a/core/os/keyboard.h +++ b/core/os/keyboard.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef KEYBOARD_H #define KEYBOARD_H -#include "core/ustring.h" +#include "core/string/ustring.h" /* Special Key: @@ -294,11 +294,9 @@ enum KeyList { KEY_DIVISION = 0x00F7, KEY_YDIAERESIS = 0x00FF, - }; enum KeyModifierMask { - KEY_CODE_MASK = ((1 << 25) - 1), ///< Apply this mask to any keycode to remove modifiers. KEY_MODIFIER_MASK = (0xFF << 24), ///< Apply this mask to isolate modifiers. KEY_MASK_SHIFT = (1 << 25), @@ -314,7 +312,6 @@ enum KeyModifierMask { KEY_MASK_KPAD = (1 << 29), KEY_MASK_GROUP_SWITCH = (1 << 30) // bit 31 can't be used because variant uses regular 32 bits int as datatype - }; String keycode_get_string(uint32_t p_code); diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp index 434f6fa300..016d9d0a09 100644 --- a/core/os/main_loop.cpp +++ b/core/os/main_loop.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,17 +30,12 @@ #include "main_loop.h" -#include "core/script_language.h" +#include "core/object/script_language.h" void MainLoop::_bind_methods() { - ClassDB::bind_method(D_METHOD("init"), &MainLoop::init); - ClassDB::bind_method(D_METHOD("iteration", "delta"), &MainLoop::iteration); - ClassDB::bind_method(D_METHOD("idle", "delta"), &MainLoop::idle); - ClassDB::bind_method(D_METHOD("finish"), &MainLoop::finish); - BIND_VMETHOD(MethodInfo("_initialize")); - BIND_VMETHOD(MethodInfo(Variant::BOOL, "_iteration", PropertyInfo(Variant::FLOAT, "delta"))); - BIND_VMETHOD(MethodInfo(Variant::BOOL, "_idle", PropertyInfo(Variant::FLOAT, "delta"))); + BIND_VMETHOD(MethodInfo(Variant::BOOL, "_physics_process", PropertyInfo(Variant::FLOAT, "delta"))); + BIND_VMETHOD(MethodInfo(Variant::BOOL, "_process", PropertyInfo(Variant::FLOAT, "delta"))); BIND_VMETHOD(MethodInfo("_finalize")); BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING); @@ -52,17 +47,18 @@ void MainLoop::_bind_methods() { BIND_CONSTANT(NOTIFICATION_APPLICATION_PAUSED); BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_IN); BIND_CONSTANT(NOTIFICATION_APPLICATION_FOCUS_OUT); + BIND_CONSTANT(NOTIFICATION_TEXT_SERVER_CHANGED); ADD_SIGNAL(MethodInfo("on_request_permissions_result", PropertyInfo(Variant::STRING, "permission"), PropertyInfo(Variant::BOOL, "granted"))); }; -void MainLoop::set_init_script(const Ref<Script> &p_init_script) { - init_script = p_init_script; +void MainLoop::set_initialize_script(const Ref<Script> &p_initialize_script) { + initialize_script = p_initialize_script; } -void MainLoop::init() { - if (init_script.is_valid()) { - set_script(init_script); +void MainLoop::initialize() { + if (initialize_script.is_valid()) { + set_script(initialize_script); } if (get_script_instance()) { @@ -70,23 +66,23 @@ void MainLoop::init() { } } -bool MainLoop::iteration(float p_time) { +bool MainLoop::physics_process(float p_time) { if (get_script_instance()) { - return get_script_instance()->call("_iteration", p_time); + return get_script_instance()->call("_physics_process", p_time); } return false; } -bool MainLoop::idle(float p_time) { +bool MainLoop::process(float p_time) { if (get_script_instance()) { - return get_script_instance()->call("_idle", p_time); + return get_script_instance()->call("_process", p_time); } return false; } -void MainLoop::finish() { +void MainLoop::finalize() { if (get_script_instance()) { get_script_instance()->call("_finalize"); set_script(Variant()); //clear script diff --git a/core/os/main_loop.h b/core/os/main_loop.h index 2c34cf193c..25a09fe98f 100644 --- a/core/os/main_loop.h +++ b/core/os/main_loop.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,14 +32,14 @@ #define MAIN_LOOP_H #include "core/input/input_event.h" -#include "core/reference.h" -#include "core/script_language.h" +#include "core/object/reference.h" +#include "core/object/script_language.h" class MainLoop : public Object { GDCLASS(MainLoop, Object); OBJ_CATEGORY("Main Loop"); - Ref<Script> init_script; + Ref<Script> initialize_script; protected: static void _bind_methods(); @@ -56,14 +56,15 @@ public: NOTIFICATION_APPLICATION_PAUSED = 2015, NOTIFICATION_APPLICATION_FOCUS_IN = 2016, NOTIFICATION_APPLICATION_FOCUS_OUT = 2017, + NOTIFICATION_TEXT_SERVER_CHANGED = 2018, }; - virtual void init(); - virtual bool iteration(float p_time); - virtual bool idle(float p_time); - virtual void finish(); + virtual void initialize(); + virtual bool physics_process(float p_time); + virtual bool process(float p_time); + virtual void finalize(); - void set_init_script(const Ref<Script> &p_init_script); + void set_initialize_script(const Ref<Script> &p_initialize_script); MainLoop() {} virtual ~MainLoop() {} diff --git a/core/os/memory.cpp b/core/os/memory.cpp index 8457c52092..14808c2ce6 100644 --- a/core/os/memory.cpp +++ b/core/os/memory.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,9 @@ #include "memory.h" -#include "core/error_macros.h" +#include "core/error/error_macros.h" #include "core/os/copymem.h" -#include "core/safe_refcount.h" +#include "core/templates/safe_refcount.h" #include <stdio.h> #include <stdlib.h> diff --git a/core/os/memory.h b/core/os/memory.h index 46ffb4124b..c2ae3f4ae7 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef MEMORY_H #define MEMORY_H -#include "core/error_macros.h" -#include "core/safe_refcount.h" +#include "core/error/error_macros.h" +#include "core/templates/safe_refcount.h" #include <stddef.h> diff --git a/core/os/midi_driver.cpp b/core/os/midi_driver.cpp index e9919aeb86..a8be84c56c 100644 --- a/core/os/midi_driver.cpp +++ b/core/os/midi_driver.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/os/midi_driver.h b/core/os/midi_driver.h index bc922e1fcf..ccf624e07e 100644 --- a/core/os/midi_driver.h +++ b/core/os/midi_driver.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,7 @@ #define MIDI_DRIVER_H #include "core/typedefs.h" -#include "core/variant.h" +#include "core/variant/variant.h" /** * Multi-Platform abstraction for accessing to MIDI. diff --git a/core/os/mutex.cpp b/core/os/mutex.cpp index 31a0dc2bfa..b7d7752d35 100644 --- a/core/os/mutex.cpp +++ b/core/os/mutex.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/os/mutex.h b/core/os/mutex.h index d42cbed821..d77ec362a1 100644 --- a/core/os/mutex.h +++ b/core/os/mutex.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef MUTEX_H #define MUTEX_H -#include "core/error_list.h" +#include "core/error/error_list.h" #include "core/typedefs.h" #if !defined(NO_THREADS) diff --git a/core/os/os.cpp b/core/os/os.cpp index 3a398316bd..182bab4058 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,11 +30,11 @@ #include "os.h" +#include "core/config/project_settings.h" #include "core/input/input.h" #include "core/os/dir_access.h" #include "core/os/file_access.h" #include "core/os/midi_driver.h" -#include "core/project_settings.h" #include "core/version_generated.gen.h" #include "servers/audio_server.h" @@ -505,12 +505,8 @@ void OS::add_frame_delay(bool p_can_draw) { } OS::OS() { - void *volatile stack_bottom; - singleton = this; - _stack_bottom = (void *)(&stack_bottom); - Vector<Logger *> loggers; loggers.push_back(memnew(StdLogger)); _set_logger(memnew(CompositeLogger(loggers))); diff --git a/core/os/os.h b/core/os/os.h index 4c1d930107..ed3c6ddc94 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,13 +31,13 @@ #ifndef OS_H #define OS_H -#include "core/engine.h" -#include "core/image.h" +#include "core/config/engine.h" +#include "core/io/image.h" #include "core/io/logger.h" -#include "core/list.h" #include "core/os/main_loop.h" -#include "core/ustring.h" -#include "core/vector.h" +#include "core/string/ustring.h" +#include "core/templates/list.h" +#include "core/templates/vector.h" #include <stdarg.h> @@ -62,8 +62,6 @@ class OS { char *last_error; - void *_stack_bottom; - CompositeLogger *_logger = nullptr; bool restart_on_exit = false; @@ -77,7 +75,6 @@ public: typedef bool (*HasServerFeatureCallback)(const String &p_feature); enum RenderThreadMode { - RENDER_THREAD_UNSAFE, RENDER_THREAD_SAFE, RENDER_SEPARATE_THREAD diff --git a/core/pool_allocator.cpp b/core/os/pool_allocator.cpp index b222c20a00..b538ca0c96 100644 --- a/core/pool_allocator.cpp +++ b/core/os/pool_allocator.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,11 +30,11 @@ #include "pool_allocator.h" -#include "core/error_macros.h" +#include "core/error/error_macros.h" #include "core/os/copymem.h" #include "core/os/memory.h" #include "core/os/os.h" -#include "core/print_string.h" +#include "core/string/print_string.h" #include <assert.h> diff --git a/core/pool_allocator.h b/core/os/pool_allocator.h index 7d77af6266..15e50dac90 100644 --- a/core/pool_allocator.h +++ b/core/os/pool_allocator.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -43,7 +43,6 @@ */ enum { - POOL_ALLOCATOR_INVALID_ID = -1 ///< default invalid value. use INVALID_ID( id ) to test }; diff --git a/core/os/rw_lock.cpp b/core/os/rw_lock.cpp index a668fe2b4c..26db0aab30 100644 --- a/core/os/rw_lock.cpp +++ b/core/os/rw_lock.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "rw_lock.h" -#include "core/error_macros.h" +#include "core/error/error_macros.h" #include <stddef.h> diff --git a/core/os/rw_lock.h b/core/os/rw_lock.h index 1035072cce..ff6ad3cc4a 100644 --- a/core/os/rw_lock.h +++ b/core/os/rw_lock.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef RW_LOCK_H #define RW_LOCK_H -#include "core/error_list.h" +#include "core/error/error_list.h" class RWLock { protected: diff --git a/core/os/semaphore.h b/core/os/semaphore.h index 077e04704b..01ae7a3c65 100644 --- a/core/os/semaphore.h +++ b/core/os/semaphore.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef SEMAPHORE_H #define SEMAPHORE_H -#include "core/error_list.h" +#include "core/error/error_list.h" #include "core/typedefs.h" #if !defined(NO_THREADS) diff --git a/core/spin_lock.h b/core/os/spin_lock.h index 1bb810bb29..929e8b9a58 100644 --- a/core/spin_lock.h +++ b/core/os/spin_lock.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/os/thread.cpp b/core/os/thread.cpp index fc0ce3c9b4..0ed8825452 100644 --- a/core/os/thread.cpp +++ b/core/os/thread.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/os/thread.h b/core/os/thread.h index f761d4ca43..993c7ad33d 100644 --- a/core/os/thread.h +++ b/core/os/thread.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,15 +31,14 @@ #ifndef THREAD_H #define THREAD_H +#include "core/string/ustring.h" #include "core/typedefs.h" -#include "core/ustring.h" typedef void (*ThreadCreateCallback)(void *p_userdata); class Thread { public: enum Priority { - PRIORITY_LOW, PRIORITY_NORMAL, PRIORITY_HIGH diff --git a/core/os/thread_dummy.cpp b/core/os/thread_dummy.cpp index 2672cd7ad9..006757b8e4 100644 --- a/core/os/thread_dummy.cpp +++ b/core/os/thread_dummy.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/os/thread_dummy.h b/core/os/thread_dummy.h index 37d9ee0846..35e19732bf 100644 --- a/core/os/thread_dummy.h +++ b/core/os/thread_dummy.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/os/thread_safe.h b/core/os/thread_safe.h index 670ee8b125..81de079bf3 100644 --- a/core/os/thread_safe.h +++ b/core/os/thread_safe.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/os/threaded_array_processor.h b/core/os/threaded_array_processor.h index d27399e4cc..57f3de20bf 100644 --- a/core/os/threaded_array_processor.h +++ b/core/os/threaded_array_processor.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,7 +35,7 @@ #include "core/os/os.h" #include "core/os/thread.h" #include "core/os/thread_safe.h" -#include "core/safe_refcount.h" +#include "core/templates/safe_refcount.h" template <class C, class U> struct ThreadArrayProcessData { diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index a2b3f75bea..9eef7700f9 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,24 +30,24 @@ #include "register_core_types.h" -#include "core/bind/core_bind.h" -#include "core/class_db.h" -#include "core/compressed_translation.h" +#include "core/config/engine.h" +#include "core/config/project_settings.h" +#include "core/core_bind.h" #include "core/core_string_names.h" #include "core/crypto/aes_context.h" #include "core/crypto/crypto.h" #include "core/crypto/hashing_context.h" -#include "core/engine.h" -#include "core/func_ref.h" #include "core/input/input.h" #include "core/input/input_map.h" #include "core/io/config_file.h" #include "core/io/dtls_server.h" #include "core/io/http_client.h" #include "core/io/image_loader.h" +#include "core/io/json.h" #include "core/io/marshalls.h" #include "core/io/multiplayer_api.h" #include "core/io/networked_multiplayer_peer.h" +#include "core/io/packed_data_container.h" #include "core/io/packet_peer.h" #include "core/io/packet_peer_dtls.h" #include "core/io/packet_peer_udp.h" @@ -65,11 +65,11 @@ #include "core/math/geometry_3d.h" #include "core/math/random_number_generator.h" #include "core/math/triangle_mesh.h" +#include "core/object/class_db.h" +#include "core/object/undo_redo.h" #include "core/os/main_loop.h" -#include "core/packed_data_container.h" -#include "core/project_settings.h" -#include "core/translation.h" -#include "core/undo_redo.h" +#include "core/string/compressed_translation.h" +#include "core/string/translation.h" static Ref<ResourceFormatSaverBinary> resource_saver_binary; static Ref<ResourceFormatLoaderBinary> resource_loader_binary; @@ -97,8 +97,6 @@ extern Mutex _global_mutex; extern void register_global_constants(); extern void unregister_global_constants(); -extern void register_variant_methods(); -extern void unregister_variant_methods(); void register_core_types() { //consistency check @@ -111,7 +109,8 @@ void register_core_types() { ResourceLoader::initialize(); register_global_constants(); - register_variant_methods(); + + Variant::register_types(); CoreStringNames::create(); @@ -155,7 +154,6 @@ void register_core_types() { ClassDB::register_class<InputEventPanGesture>(); ClassDB::register_class<InputEventMIDI>(); - ClassDB::register_class<FuncRef>(); ClassDB::register_virtual_class<StreamPeer>(); ClassDB::register_class<StreamPeerBuffer>(); ClassDB::register_class<StreamPeerTCP>(); @@ -170,6 +168,7 @@ void register_core_types() { ClassDB::register_class<AESContext>(); ClassDB::register_custom_instance_class<X509Certificate>(); ClassDB::register_custom_instance_class<CryptoKey>(); + ClassDB::register_custom_instance_class<HMACContext>(); ClassDB::register_custom_instance_class<Crypto>(); ClassDB::register_custom_instance_class<StreamPeerSSL>(); @@ -200,6 +199,7 @@ void register_core_types() { ClassDB::register_class<_Semaphore>(); ClassDB::register_class<XMLParser>(); + ClassDB::register_class<JSONParser>(); ClassDB::register_class<ConfigFile>(); @@ -319,7 +319,8 @@ void unregister_core_types() { ClassDB::cleanup_defaults(); ObjectDB::cleanup(); - unregister_variant_methods(); + Variant::unregister_types(); + unregister_global_constants(); ClassDB::cleanup(); diff --git a/core/register_core_types.h b/core/register_core_types.h index bdd335f33c..baf7ddbe65 100644 --- a/core/register_core_types.h +++ b/core/register_core_types.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/string/SCsub b/core/string/SCsub new file mode 100644 index 0000000000..3217166f18 --- /dev/null +++ b/core/string/SCsub @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +Import("env") + +env_string = env.Clone() + +env_string.add_source_files(env.core_sources, "*.cpp") diff --git a/core/compressed_translation.cpp b/core/string/compressed_translation.cpp index a92275565d..ad90924293 100644 --- a/core/compressed_translation.cpp +++ b/core/string/compressed_translation.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "compressed_translation.h" -#include "core/pair.h" +#include "core/templates/pair.h" extern "C" { #include "thirdparty/misc/smaz.h" diff --git a/core/compressed_translation.h b/core/string/compressed_translation.h index c8b3cd2330..0abb770178 100644 --- a/core/compressed_translation.h +++ b/core/string/compressed_translation.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef COMPRESSED_TRANSLATION_H #define COMPRESSED_TRANSLATION_H -#include "core/translation.h" +#include "core/string/translation.h" class PHashTranslation : public Translation { GDCLASS(PHashTranslation, Translation); diff --git a/core/node_path.cpp b/core/string/node_path.cpp index 2a51dca74a..d3afa7b4dd 100644 --- a/core/node_path.cpp +++ b/core/string/node_path.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "node_path.h" -#include "core/print_string.h" +#include "core/string/print_string.h" void NodePath::_update_hash_cache() const { uint32_t h = data->absolute ? 1 : 0; @@ -288,7 +288,7 @@ void NodePath::simplify() { if (data->path[i].operator String() == ".") { data->path.remove(i); i--; - } else if (data->path[i].operator String() == ".." && i > 0 && data->path[i - 1].operator String() != "." && data->path[i - 1].operator String() != "..") { + } else if (i > 0 && data->path[i].operator String() == ".." && data->path[i - 1].operator String() != "." && data->path[i - 1].operator String() != "..") { //remove both data->path.remove(i - 1); data->path.remove(i - 1); diff --git a/core/node_path.h b/core/string/node_path.h index 7c06bf01ce..26e15636d9 100644 --- a/core/node_path.h +++ b/core/string/node_path.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef NODE_PATH_H #define NODE_PATH_H -#include "core/string_name.h" -#include "core/ustring.h" +#include "core/string/string_name.h" +#include "core/string/ustring.h" class NodePath { struct Data { diff --git a/core/print_string.cpp b/core/string/print_string.cpp index 54de229471..345371d733 100644 --- a/core/print_string.cpp +++ b/core/string/print_string.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/print_string.h b/core/string/print_string.h index 4d03f4a6de..1a9ff1efd6 100644 --- a/core/print_string.h +++ b/core/string/print_string.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef PRINT_STRING_H #define PRINT_STRING_H -#include "core/ustring.h" +#include "core/string/ustring.h" extern void (*_print_func)(String); diff --git a/core/string_buffer.h b/core/string/string_buffer.h index a685720851..33897c3674 100644 --- a/core/string_buffer.h +++ b/core/string/string_buffer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef STRING_BUFFER_H #define STRING_BUFFER_H -#include "core/ustring.h" +#include "core/string/ustring.h" template <int SHORT_BUFFER_SIZE = 64> class StringBuffer { @@ -40,7 +40,7 @@ class StringBuffer { int string_length = 0; _FORCE_INLINE_ char32_t *current_buffer_ptr() { - return static_cast<String &>(buffer).empty() ? short_buffer : buffer.ptrw(); + return static_cast<String &>(buffer).is_empty() ? short_buffer : buffer.ptrw(); } public: @@ -122,7 +122,7 @@ StringBuffer<SHORT_BUFFER_SIZE> &StringBuffer<SHORT_BUFFER_SIZE>::reserve(int p_ return *this; } - bool need_copy = string_length > 0 && buffer.empty(); + bool need_copy = string_length > 0 && buffer.is_empty(); buffer.resize(next_power_of_2(p_size)); if (need_copy) { memcpy(buffer.ptrw(), short_buffer, string_length * sizeof(char32_t)); @@ -139,7 +139,7 @@ int StringBuffer<SHORT_BUFFER_SIZE>::length() const { template <int SHORT_BUFFER_SIZE> String StringBuffer<SHORT_BUFFER_SIZE>::as_string() { current_buffer_ptr()[string_length] = '\0'; - if (buffer.empty()) { + if (buffer.is_empty()) { return String(short_buffer); } else { buffer.resize(string_length + 1); diff --git a/core/string_builder.cpp b/core/string/string_builder.cpp index dec299ffa3..834c87c845 100644 --- a/core/string_builder.cpp +++ b/core/string/string_builder.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/string_builder.h b/core/string/string_builder.h index 2a37d14218..30ce2a06f7 100644 --- a/core/string_builder.h +++ b/core/string/string_builder.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef STRING_BUILDER_H #define STRING_BUILDER_H -#include "core/ustring.h" -#include "core/vector.h" +#include "core/string/ustring.h" +#include "core/templates/vector.h" class StringBuilder { uint32_t string_length = 0; diff --git a/core/string_name.cpp b/core/string/string_name.cpp index 6260e3ce8c..14b87072bb 100644 --- a/core/string_name.cpp +++ b/core/string/string_name.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #include "string_name.h" #include "core/os/os.h" -#include "core/print_string.h" +#include "core/string/print_string.h" StaticCString StaticCString::create(const char *p_ptr) { StaticCString scs; @@ -377,3 +377,17 @@ StringName StringName::search(const String &p_name) { StringName::~StringName() { unref(); } + +bool operator==(const String &p_name, const StringName &p_string_name) { + return p_name == p_string_name.operator String(); +} +bool operator!=(const String &p_name, const StringName &p_string_name) { + return p_name != p_string_name.operator String(); +} + +bool operator==(const char *p_name, const StringName &p_string_name) { + return p_name == p_string_name.operator String(); +} +bool operator!=(const char *p_name, const StringName &p_string_name) { + return p_name != p_string_name.operator String(); +} diff --git a/core/string_name.h b/core/string/string_name.h index 4f90479bda..44d0ea14fa 100644 --- a/core/string_name.h +++ b/core/string/string_name.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,8 +32,8 @@ #define STRING_NAME_H #include "core/os/mutex.h" -#include "core/safe_refcount.h" -#include "core/ustring.h" +#include "core/string/ustring.h" +#include "core/templates/safe_refcount.h" class Main; @@ -44,7 +44,6 @@ struct StaticCString { class StringName { enum { - STRING_TABLE_BITS = 12, STRING_TABLE_LEN = 1 << STRING_TABLE_BITS, STRING_TABLE_MASK = STRING_TABLE_LEN - 1 @@ -84,7 +83,7 @@ class StringName { StringName(_Data *p_data) { _data = p_data; } public: - operator const void *() const { return (_data && (_data->cname || !_data->name.empty())) ? (void *)1 : nullptr; } + operator const void *() const { return (_data && (_data->cname || !_data->name.is_empty())) ? (void *)1 : nullptr; } bool operator==(const String &p_name) const; bool operator==(const char *p_name) const; @@ -155,6 +154,11 @@ public: ~StringName(); }; +bool operator==(const String &p_name, const StringName &p_string_name); +bool operator!=(const String &p_name, const StringName &p_string_name); +bool operator==(const char *p_name, const StringName &p_string_name); +bool operator!=(const char *p_name, const StringName &p_string_name); + StringName _scs_create(const char *p_chr); #endif // STRING_NAME_H diff --git a/core/translation.cpp b/core/string/translation.cpp index 8c8ca06740..5337d46aa3 100644 --- a/core/translation.cpp +++ b/core/string/translation.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,14 @@ #include "translation.h" +#include "core/config/project_settings.h" #include "core/io/resource_loader.h" #include "core/os/os.h" -#include "core/project_settings.h" + +#ifdef TOOLS_ENABLED +#include "editor/editor_settings.h" +#include "main/main.h" +#endif // ISO 639-1 language codes, with the addition of glibc locales with their // regional identifiers. This list must match the language names (in English) @@ -846,7 +851,7 @@ void Translation::add_message(const StringName &p_src_text, const StringName &p_ void Translation::add_plural_message(const StringName &p_src_text, const Vector<String> &p_plural_xlated_texts, const StringName &p_context) { WARN_PRINT("Translation class doesn't handle plural messages. Calling add_plural_message() on a Translation instance is probably a mistake. \nUse a derived Translation class that handles plurals, such as TranslationPO class"); - ERR_FAIL_COND_MSG(p_plural_xlated_texts.empty(), "Parameter vector p_plural_xlated_texts passed in is empty."); + ERR_FAIL_COND_MSG(p_plural_xlated_texts.is_empty(), "Parameter vector p_plural_xlated_texts passed in is empty."); translation_map[p_src_text] = p_plural_xlated_texts[0]; } @@ -1214,6 +1219,22 @@ void TranslationServer::set_tool_translation(const Ref<Translation> &p_translati tool_translation = p_translation; } +Ref<Translation> TranslationServer::get_tool_translation() const { + return tool_translation; +} + +String TranslationServer::get_tool_locale() { +#ifdef TOOLS_ENABLED + if (TranslationServer::get_singleton()->get_tool_translation().is_valid() && (Engine::get_singleton()->is_editor_hint() || Main::is_project_manager())) { + return tool_translation->get_locale(); + } else { +#else + { +#endif + return get_locale(); + } +} + StringName TranslationServer::tool_translate(const StringName &p_message, const StringName &p_context) const { if (tool_translation.is_valid()) { StringName r = tool_translation->get_message(p_message, p_context); diff --git a/core/translation.h b/core/string/translation.h index cba25a434f..72a828227e 100644 --- a/core/translation.h +++ b/core/string/translation.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef TRANSLATION_H #define TRANSLATION_H -#include "core/resource.h" +#include "core/io/resource.h" class Translation : public Resource { GDCLASS(Translation, Resource); @@ -110,7 +110,9 @@ public: static String standardize_locale(const String &p_locale); static String get_language_code(const String &p_locale); + String get_tool_locale(); void set_tool_translation(const Ref<Translation> &p_translation); + Ref<Translation> get_tool_translation() const; StringName tool_translate(const StringName &p_message, const StringName &p_context = "") const; StringName tool_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const; void set_doc_translation(const Ref<Translation> &p_translation); diff --git a/core/translation_po.cpp b/core/string/translation_po.cpp index 203f29026b..846afe761b 100644 --- a/core/translation_po.cpp +++ b/core/string/translation_po.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -230,7 +230,7 @@ StringName TranslationPO::get_message(const StringName &p_src_text, const String if (!translation_map.has(p_context) || !translation_map[p_context].has(p_src_text)) { return StringName(); } - ERR_FAIL_COND_V_MSG(translation_map[p_context][p_src_text].empty(), StringName(), "Source text \"" + String(p_src_text) + "\" is registered but doesn't have a translation. Please report this bug."); + ERR_FAIL_COND_V_MSG(translation_map[p_context][p_src_text].is_empty(), StringName(), "Source text \"" + String(p_src_text) + "\" is registered but doesn't have a translation. Please report this bug."); return translation_map[p_context][p_src_text][0]; } @@ -246,7 +246,7 @@ StringName TranslationPO::get_plural_message(const StringName &p_src_text, const if (!translation_map.has(p_context) || !translation_map[p_context].has(p_src_text)) { return StringName(); } - ERR_FAIL_COND_V_MSG(translation_map[p_context][p_src_text].empty(), StringName(), "Source text \"" + String(p_src_text) + "\" is registered but doesn't have a translation. Please report this bug."); + ERR_FAIL_COND_V_MSG(translation_map[p_context][p_src_text].is_empty(), StringName(), "Source text \"" + String(p_src_text) + "\" is registered but doesn't have a translation. Please report this bug."); if (translation_map[p_context][p_src_text].size() == 1) { WARN_PRINT("Source string \"" + String(p_src_text) + "\" doesn't have plural translations. Use singular translation API for such as tr(), TTR() to translate \"" + String(p_src_text) + "\""); diff --git a/core/translation_po.h b/core/string/translation_po.h index 88830210ef..0e1d03d6ca 100644 --- a/core/translation_po.h +++ b/core/string/translation_po.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,7 +34,7 @@ //#define DEBUG_TRANSLATION_PO #include "core/math/expression.h" -#include "core/translation.h" +#include "core/string/translation.h" class TranslationPO : public Translation { GDCLASS(TranslationPO, Translation); diff --git a/core/ucaps.h b/core/string/ucaps.h index 79b346acba..b785ac7879 100644 --- a/core/ucaps.h +++ b/core/string/ucaps.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/ustring.cpp b/core/string/ustring.cpp index e382ef3746..21336a99ec 100644 --- a/core/ustring.cpp +++ b/core/string/ustring.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,14 +30,14 @@ #include "ustring.h" -#include "core/color.h" #include "core/crypto/crypto_core.h" +#include "core/math/color.h" #include "core/math/math_funcs.h" #include "core/os/memory.h" -#include "core/print_string.h" -#include "core/translation.h" -#include "core/ucaps.h" -#include "core/variant.h" +#include "core/string/print_string.h" +#include "core/string/translation.h" +#include "core/string/ucaps.h" +#include "core/variant/variant.h" #include <cstdint> @@ -209,7 +209,6 @@ void CharString::copy_from(const char *p_cstr) { /* String */ /*************************************************************************/ -//TODO: move to TextServer //kind of poor should be rewritten properly String String::word_wrap(int p_chars_per_line) const { int from = 0; @@ -428,12 +427,12 @@ String operator+(char32_t p_chr, const String &p_str) { } String &String::operator+=(const String &p_str) { - if (empty()) { + if (is_empty()) { *this = p_str; return *this; } - if (p_str.empty()) { + if (p_str.is_empty()) { return *this; } @@ -520,7 +519,7 @@ bool String::operator==(const char *p_str) const { if (length() != len) { return false; } - if (empty()) { + if (is_empty()) { return true; } @@ -559,7 +558,7 @@ bool String::operator==(const char32_t *p_str) const { if (length() != len) { return false; } - if (empty()) { + if (is_empty()) { return true; } @@ -581,7 +580,7 @@ bool String::operator==(const String &p_str) const { if (length() != p_str.length()) { return false; } - if (empty()) { + if (is_empty()) { return true; } @@ -606,7 +605,7 @@ bool String::operator==(const StrRange &p_str_range) const { if (length() != len) { return false; } - if (empty()) { + if (is_empty()) { return true; } @@ -637,6 +636,20 @@ bool operator==(const wchar_t *p_chr, const String &p_str) { #endif } +bool operator!=(const char *p_chr, const String &p_str) { + return !(p_str == p_chr); +} + +bool operator!=(const wchar_t *p_chr, const String &p_str) { +#ifdef WINDOWS_ENABLED + // wchar_t is 16-bit + return !(p_str == String::utf16((const char16_t *)p_chr)); +#else + // wchar_t is 32-bi + return !(p_str == String((const char32_t *)p_chr)); +#endif +} + bool String::operator!=(const char *p_str) const { return (!(*this == p_str)); } @@ -654,24 +667,31 @@ bool String::operator!=(const String &p_str) const { } bool String::operator<=(const String &p_str) const { - return (*this < p_str) || (*this == p_str); + return !(p_str < *this); +} + +bool String::operator>(const String &p_str) const { + return p_str < *this; +} +bool String::operator>=(const String &p_str) const { + return !(*this < p_str); } bool String::operator<(const char *p_str) const { - if (empty() && p_str[0] == 0) { + if (is_empty() && p_str[0] == 0) { return false; } - if (empty()) { + if (is_empty()) { return true; } return is_str_less(get_data(), p_str); } bool String::operator<(const wchar_t *p_str) const { - if (empty() && p_str[0] == 0) { + if (is_empty() && p_str[0] == 0) { return false; } - if (empty()) { + if (is_empty()) { return true; } @@ -685,10 +705,10 @@ bool String::operator<(const wchar_t *p_str) const { } bool String::operator<(const char32_t *p_str) const { - if (empty() && p_str[0] == 0) { + if (is_empty() && p_str[0] == 0) { return false; } - if (empty()) { + if (is_empty()) { return true; } @@ -700,13 +720,13 @@ bool String::operator<(const String &p_str) const { } signed char String::nocasecmp_to(const String &p_str) const { - if (empty() && p_str.empty()) { + if (is_empty() && p_str.is_empty()) { return 0; } - if (empty()) { + if (is_empty()) { return -1; } - if (p_str.empty()) { + if (p_str.is_empty()) { return 1; } @@ -732,13 +752,13 @@ signed char String::nocasecmp_to(const String &p_str) const { } signed char String::casecmp_to(const String &p_str) const { - if (empty() && p_str.empty()) { + if (is_empty() && p_str.is_empty()) { return 0; } - if (empty()) { + if (is_empty()) { return -1; } - if (p_str.empty()) { + if (p_str.is_empty()) { return 1; } @@ -929,10 +949,10 @@ String String::get_with_code_lines() const { } int String::get_slice_count(String p_splitter) const { - if (empty()) { + if (is_empty()) { return 0; } - if (p_splitter.empty()) { + if (p_splitter.is_empty()) { return 0; } @@ -948,7 +968,7 @@ int String::get_slice_count(String p_splitter) const { } String String::get_slice(String p_splitter, int p_slice) const { - if (empty() || p_splitter.empty()) { + if (is_empty() || p_splitter.is_empty()) { return ""; } @@ -988,7 +1008,7 @@ String String::get_slice(String p_splitter, int p_slice) const { } String String::get_slicec(char32_t p_splitter, int p_slice) const { - if (empty()) { + if (is_empty()) { return String(); } @@ -2565,7 +2585,7 @@ int64_t String::to_int(const char32_t *p_str, int p_len, bool p_clamp) { } double String::to_float() const { - if (empty()) { + if (is_empty()) { return 0; } return built_in_strtod<char32_t>(get_data()); @@ -2747,7 +2767,7 @@ String String::substr(int p_from, int p_chars) const { p_chars = length() - p_from; } - if (empty() || p_from < 0 || p_from >= length() || p_chars <= 0) { + if (is_empty() || p_from < 0 || p_from >= length() || p_chars <= 0) { return ""; } @@ -3122,7 +3142,7 @@ bool String::is_quoted() const { } int String::_count(const String &p_string, int p_from, int p_to, bool p_case_insensitive) const { - if (p_string.empty()) { + if (p_string.is_empty()) { return 0; } int len = length(); @@ -3843,7 +3863,6 @@ String String::xml_escape(bool p_escape_quotes) const { } /* for (int i=1;i<32;i++) { - char chr[2]={i,0}; str=str.replace(chr,"&#"+String::num(i)+";"); }*/ @@ -4222,7 +4241,7 @@ bool String::is_valid_ip_address() const { Vector<String> ip = split(":"); for (int i = 0; i < ip.size(); i++) { String n = ip[i]; - if (n.empty()) { + if (n.is_empty()) { continue; } if (n.is_valid_hex_number(false)) { @@ -4266,7 +4285,10 @@ bool String::is_rel_path() const { } String String::get_base_dir() const { - int basepos = find("://"); + int basepos = find(":/"); + if (basepos == -1) { + basepos = find(":\\"); + } String rs; String base; if (basepos != -1) { @@ -4309,7 +4331,7 @@ String String::get_extension() const { } String String::plus_file(const String &p_file) const { - if (empty()) { + if (is_empty()) { return p_file; } if (operator[](length() - 1) == '/' || (p_file.size() > 0 && p_file.operator[](0) == '/')) { @@ -4455,7 +4477,9 @@ String String::sprintf(const Array &values, bool *error) const { bool left_justified = false; bool show_sign = false; - *error = true; + if (error) { + *error = true; + } for (; *self; self++) { const char32_t c = *self; @@ -4716,7 +4740,9 @@ String String::sprintf(const Array &values, bool *error) const { return "not all arguments converted during string formatting"; } - *error = false; + if (error) { + *error = false; + } return formatted; } @@ -4732,6 +4758,69 @@ String String::unquote() const { return substr(1, length() - 2); } +Vector<uint8_t> String::to_ascii_buffer() const { + const String *s = this; + if (s->is_empty()) { + return Vector<uint8_t>(); + } + CharString charstr = s->ascii(); + + Vector<uint8_t> retval; + size_t len = charstr.length(); + retval.resize(len); + uint8_t *w = retval.ptrw(); + copymem(w, charstr.ptr(), len); + + return retval; +} + +Vector<uint8_t> String::to_utf8_buffer() const { + const String *s = this; + if (s->is_empty()) { + return Vector<uint8_t>(); + } + CharString charstr = s->utf8(); + + Vector<uint8_t> retval; + size_t len = charstr.length(); + retval.resize(len); + uint8_t *w = retval.ptrw(); + copymem(w, charstr.ptr(), len); + + return retval; +} + +Vector<uint8_t> String::to_utf16_buffer() const { + const String *s = this; + if (s->is_empty()) { + return Vector<uint8_t>(); + } + Char16String charstr = s->utf16(); + + Vector<uint8_t> retval; + size_t len = charstr.length() * sizeof(char16_t); + retval.resize(len); + uint8_t *w = retval.ptrw(); + copymem(w, (const void *)charstr.ptr(), len); + + return retval; +} + +Vector<uint8_t> String::to_utf32_buffer() const { + const String *s = this; + if (s->is_empty()) { + return Vector<uint8_t>(); + } + + Vector<uint8_t> retval; + size_t len = s->length() * sizeof(char32_t); + retval.resize(len); + uint8_t *w = retval.ptrw(); + copymem(w, (const void *)s->ptr(), len); + + return retval; +} + #ifdef TOOLS_ENABLED String TTR(const String &p_text, const String &p_context) { if (TranslationServer::get_singleton()) { diff --git a/core/ustring.h b/core/string/ustring.h index 1f8a5d7e7d..654e327320 100644 --- a/core/ustring.h +++ b/core/string/ustring.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,13 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef USTRING_H -#define USTRING_H +#ifndef USTRING_GODOT_H +#define USTRING_GODOT_H +// Note: Renamed to avoid conflict with ICU header with the same name. -#include "core/array.h" -#include "core/cowdata.h" +#include "core/templates/cowdata.h" +#include "core/templates/vector.h" #include "core/typedefs.h" -#include "core/vector.h" +#include "core/variant/array.h" /*************************************************************************/ /* CharProxy */ @@ -198,7 +199,6 @@ class String { public: enum { - npos = -1 ///<for "some" compatibility with std::string (npos is a huge value in std::string) }; @@ -254,6 +254,8 @@ public: bool operator<(const String &p_str) const; bool operator<=(const String &p_str) const; + bool operator>(const String &p_str) const; + bool operator>=(const String &p_str) const; signed char casecmp_to(const String &p_str) const; signed char nocasecmp_to(const String &p_str) const; @@ -392,7 +394,7 @@ public: Vector<uint8_t> sha1_buffer() const; Vector<uint8_t> sha256_buffer() const; - _FORCE_INLINE_ bool empty() const { return length() == 0; } + _FORCE_INLINE_ bool is_empty() const { return length() == 0; } // path functions bool is_abs_path() const; @@ -431,15 +433,20 @@ public: /** * The constructors must not depend on other overloads */ - /* String(char32_t p_char);*/ _FORCE_INLINE_ String() {} _FORCE_INLINE_ String(const String &p_str) { _cowdata._ref(p_str._cowdata); } + String &operator=(const String &p_str) { _cowdata._ref(p_str._cowdata); return *this; } + Vector<uint8_t> to_ascii_buffer() const; + Vector<uint8_t> to_utf8_buffer() const; + Vector<uint8_t> to_utf16_buffer() const; + Vector<uint8_t> to_utf32_buffer() const; + String(const char *p_str); String(const wchar_t *p_str); String(const char32_t *p_str); @@ -451,6 +458,8 @@ public: bool operator==(const char *p_chr, const String &p_str); bool operator==(const wchar_t *p_chr, const String &p_str); +bool operator!=(const char *p_chr, const String &p_str); +bool operator!=(const wchar_t *p_chr, const String &p_str); String operator+(const char *p_chr, const String &p_str); String operator+(const wchar_t *p_chr, const String &p_str); @@ -527,4 +536,24 @@ String RTRN(const String &p_text, const String &p_text_plural, int p_n, const St bool is_symbol(char32_t c); bool select_word(const String &p_s, int p_col, int &r_beg, int &r_end); -#endif // USTRING_H +_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr) { +} + +_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str) { + arr.push_back(p_str); +} + +template <class... P> +_FORCE_INLINE_ void sarray_add_str(Vector<String> &arr, const String &p_str, P... p_args) { + arr.push_back(p_str); + sarray_add_str(arr, p_args...); +} + +template <class... P> +_FORCE_INLINE_ Vector<String> sarray(P... p_args) { + Vector<String> arr; + sarray_add_str(arr, p_args...); + return arr; +} + +#endif // USTRING_GODOT_H diff --git a/core/templates/SCsub b/core/templates/SCsub new file mode 100644 index 0000000000..8c4c843a33 --- /dev/null +++ b/core/templates/SCsub @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +Import("env") + +env_templates = env.Clone() + +env_templates.add_source_files(env.core_sources, "*.cpp") diff --git a/core/command_queue_mt.cpp b/core/templates/command_queue_mt.cpp index ace210ca2c..238bf3975c 100644 --- a/core/command_queue_mt.cpp +++ b/core/templates/command_queue_mt.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,6 +30,7 @@ #include "command_queue_mt.h" +#include "core/config/project_settings.h" #include "core/os/os.h" void CommandQueueMT::lock() { @@ -71,7 +72,7 @@ CommandQueueMT::SyncSemaphore *CommandQueueMT::_alloc_sync_sem() { bool CommandQueueMT::dealloc_one() { tryagain: - if (dealloc_ptr == write_ptr) { + if (dealloc_ptr == (write_ptr_and_epoch >> 1)) { // The queue is empty return false; } @@ -94,6 +95,10 @@ tryagain: } CommandQueueMT::CommandQueueMT(bool p_sync) { + command_mem_size = GLOBAL_DEF_RST("memory/limits/command_queue/multithreading_queue_size_kb", DEFAULT_COMMAND_MEM_SIZE_KB); + ProjectSettings::get_singleton()->set_custom_property_info("memory/limits/command_queue/multithreading_queue_size_kb", PropertyInfo(Variant::INT, "memory/limits/command_queue/multithreading_queue_size_kb", PROPERTY_HINT_RANGE, "1,4096,1,or_greater")); + command_mem_size *= 1024; + command_mem = (uint8_t *)memalloc(command_mem_size); if (p_sync) { sync = memnew(Semaphore); } diff --git a/core/command_queue_mt.h b/core/templates/command_queue_mt.h index d7a6a5bc43..7861c76153 100644 --- a/core/command_queue_mt.h +++ b/core/templates/command_queue_mt.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,7 +34,7 @@ #include "core/os/memory.h" #include "core/os/mutex.h" #include "core/os/semaphore.h" -#include "core/simple_type.h" +#include "core/templates/simple_type.h" #include "core/typedefs.h" #define COMMA(N) _COMMA_##N @@ -330,15 +330,15 @@ class CommandQueueMT { /***** BASE *******/ enum { - COMMAND_MEM_SIZE_KB = 256, - COMMAND_MEM_SIZE = COMMAND_MEM_SIZE_KB * 1024, + DEFAULT_COMMAND_MEM_SIZE_KB = 256, SYNC_SEMAPHORES = 8 }; - uint8_t *command_mem = (uint8_t *)memalloc(COMMAND_MEM_SIZE); - uint32_t read_ptr = 0; - uint32_t write_ptr = 0; + uint8_t *command_mem = nullptr; + uint32_t read_ptr_and_epoch = 0; + uint32_t write_ptr_and_epoch = 0; uint32_t dealloc_ptr = 0; + uint32_t command_mem_size = 0; SyncSemaphore sync_sems[SYNC_SEMAPHORES]; Mutex mutex; Semaphore *sync = nullptr; @@ -348,7 +348,11 @@ class CommandQueueMT { // alloc size is size+T+safeguard uint32_t alloc_size = ((sizeof(T) + 8 - 1) & ~(8 - 1)) + 8; + // Assert that the buffer is big enough to hold at least two messages. + ERR_FAIL_COND_V(alloc_size * 2 + sizeof(uint32_t) > command_mem_size, nullptr); + tryagain: + uint32_t write_ptr = write_ptr_and_epoch >> 1; if (write_ptr < dealloc_ptr) { // behind dealloc_ptr, check that there is room @@ -362,7 +366,7 @@ class CommandQueueMT { } else { // ahead of dealloc_ptr, check that there is room - if ((COMMAND_MEM_SIZE - write_ptr) < alloc_size + sizeof(uint32_t)) { + if ((command_mem_size - write_ptr) < alloc_size + sizeof(uint32_t)) { // no room at the end, wrap down; if (dealloc_ptr == 0) { // don't want write_ptr to become dealloc_ptr @@ -375,12 +379,17 @@ class CommandQueueMT { } // if this happens, it's a bug - ERR_FAIL_COND_V((COMMAND_MEM_SIZE - write_ptr) < 8, nullptr); + ERR_FAIL_COND_V((command_mem_size - write_ptr) < 8, nullptr); // zero means, wrap to beginning uint32_t *p = (uint32_t *)&command_mem[write_ptr]; - *p = 0; - write_ptr = 0; + *p = 1; + write_ptr_and_epoch = 0 | (1 & ~write_ptr_and_epoch); // Invert epoch. + // See if we can get the thread to run and clear up some more space while we wait. + // This is required if alloc_size * 2 + 4 > COMMAND_MEM_SIZE + if (sync) { + sync->post(); + } goto tryagain; } } @@ -394,6 +403,7 @@ class CommandQueueMT { // allocate the command T *cmd = memnew_placement(&command_mem[write_ptr], T); write_ptr += size; + write_ptr_and_epoch = (write_ptr << 1) | (write_ptr_and_epoch & 1); return cmd; } @@ -419,19 +429,21 @@ class CommandQueueMT { tryagain: // tried to read an empty queue - if (read_ptr == write_ptr) { + if (read_ptr_and_epoch == write_ptr_and_epoch) { if (p_lock) { unlock(); } return false; } + uint32_t read_ptr = read_ptr_and_epoch >> 1; uint32_t size_ptr = read_ptr; uint32_t size = *(uint32_t *)&command_mem[read_ptr] >> 1; if (size == 0) { + *(uint32_t *)&command_mem[read_ptr] = 0; // clear in-use bit. //end of ringbuffer, wrap - read_ptr = 0; + read_ptr_and_epoch = 0 | (1 & ~read_ptr_and_epoch); // Invert epoch. goto tryagain; } @@ -441,6 +453,8 @@ class CommandQueueMT { read_ptr += size; + read_ptr_and_epoch = (read_ptr << 1) | (read_ptr_and_epoch & 1); + if (p_lock) { unlock(); } diff --git a/core/cowdata.h b/core/templates/cowdata.h index 79676e6d80..4becb1be59 100644 --- a/core/cowdata.h +++ b/core/templates/cowdata.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +31,9 @@ #ifndef COWDATA_H #define COWDATA_H -#include "core/error_macros.h" +#include "core/error/error_macros.h" #include "core/os/memory.h" -#include "core/safe_refcount.h" +#include "core/templates/safe_refcount.h" #include <string.h> @@ -135,7 +135,7 @@ public: } _FORCE_INLINE_ void clear() { resize(0); } - _FORCE_INLINE_ bool empty() const { return _ptr == nullptr; } + _FORCE_INLINE_ bool is_empty() const { return _ptr == nullptr; } _FORCE_INLINE_ void set(int p_index, const T &p_elem) { CRASH_BAD_INDEX(p_index, size()); diff --git a/core/hash_map.h b/core/templates/hash_map.h index 10fc931e7a..dc378aed69 100644 --- a/core/hash_map.h +++ b/core/templates/hash_map.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,12 +31,12 @@ #ifndef HASH_MAP_H #define HASH_MAP_H -#include "core/error_macros.h" -#include "core/hashfuncs.h" -#include "core/list.h" +#include "core/error/error_macros.h" #include "core/math/math_funcs.h" #include "core/os/memory.h" -#include "core/ustring.h" +#include "core/string/ustring.h" +#include "core/templates/hashfuncs.h" +#include "core/templates/list.h" /** * @class HashMap @@ -73,7 +73,7 @@ public: private: friend class HashMap; - uint32_t hash; + uint32_t hash = 0; Element *next = nullptr; Element() {} Pair pair; @@ -497,7 +497,7 @@ public: return elements; } - inline bool empty() const { + inline bool is_empty() const { return elements == 0; } diff --git a/core/hashfuncs.h b/core/templates/hashfuncs.h index f4048843fc..4572b269cf 100644 --- a/core/hashfuncs.h +++ b/core/templates/hashfuncs.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,12 +33,12 @@ #include "core/math/math_defs.h" #include "core/math/math_funcs.h" -#include "core/node_path.h" -#include "core/object_id.h" -#include "core/rid.h" -#include "core/string_name.h" +#include "core/object/object_id.h" +#include "core/string/node_path.h" +#include "core/string/string_name.h" +#include "core/string/ustring.h" +#include "core/templates/rid.h" #include "core/typedefs.h" -#include "core/ustring.h" /** * Hashing functions */ @@ -114,6 +114,24 @@ static inline uint32_t make_uint32_t(T p_in) { return _u._u32; } +static inline uint64_t hash_djb2_one_float_64(double p_in, uint64_t p_prev = 5381) { + union { + double d; + uint64_t i; + } u; + + // Normalize +/- 0.0 and NaN values so they hash the same. + if (p_in == 0.0f) { + u.d = 0.0; + } else if (Math::is_nan(p_in)) { + u.d = Math_NAN; + } else { + u.d = p_in; + } + + return ((p_prev << 5) + p_prev) + u.i; +} + static inline uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev = 5381) { return ((p_prev << 5) + p_prev) + p_in; } diff --git a/core/list.h b/core/templates/list.h index 1cef3c484d..eaf1dbb4a0 100644 --- a/core/list.h +++ b/core/templates/list.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +31,9 @@ #ifndef LIST_H #define LIST_H -#include "core/error_macros.h" +#include "core/error/error_macros.h" #include "core/os/memory.h" -#include "core/sort_array.h" +#include "core/templates/sort_array.h" /** * Generic Templatized Linked List Implementation. @@ -137,9 +137,9 @@ public: private: struct _Data { - Element *first; - Element *last; - int size_cache; + Element *first = nullptr; + Element *last = nullptr; + int size_cache = 0; bool erase(const Element *p_I) { ERR_FAIL_COND_V(!p_I, false); @@ -373,7 +373,7 @@ public: /** * return whether the list is empty */ - _FORCE_INLINE_ bool empty() const { + _FORCE_INLINE_ bool is_empty() const { return (!_data || !_data->size_cache); } diff --git a/core/local_vector.h b/core/templates/local_vector.h index b0dbd22b29..4ffb93b2ad 100644 --- a/core/local_vector.h +++ b/core/templates/local_vector.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,11 +31,11 @@ #ifndef LOCAL_VECTOR_H #define LOCAL_VECTOR_H -#include "core/error_macros.h" +#include "core/error/error_macros.h" #include "core/os/copymem.h" #include "core/os/memory.h" -#include "core/sort_array.h" -#include "core/vector.h" +#include "core/templates/sort_array.h" +#include "core/templates/vector.h" template <class T, class U = uint32_t, bool force_trivial = false> class LocalVector { @@ -104,7 +104,7 @@ public: capacity = 0; } } - _FORCE_INLINE_ bool empty() const { return count == 0; } + _FORCE_INLINE_ bool is_empty() const { return count == 0; } _FORCE_INLINE_ void reserve(U p_size) { p_size = nearest_power_of_2_templated(p_size); if (p_size > capacity) { diff --git a/core/io/file_access_buffered.h b/core/templates/lru.h index 99d5ce903d..e55e40da48 100644 --- a/core/io/file_access_buffered.h +++ b/core/templates/lru.h @@ -1,12 +1,12 @@ /*************************************************************************/ -/* file_access_buffered.h */ +/* lru.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,64 +28,99 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef FILE_ACCESS_BUFFERED_H -#define FILE_ACCESS_BUFFERED_H +#ifndef LRU_H +#define LRU_H -#include "core/os/file_access.h" - -#include "core/ustring.h" - -class FileAccessBuffered : public FileAccess { -public: - enum { - DEFAULT_CACHE_SIZE = 128 * 1024, - }; +#include "core/math/math_funcs.h" +#include "hash_map.h" +#include "list.h" +template <class TKey, class TData> +class LRUCache { private: - int cache_size = DEFAULT_CACHE_SIZE; - - int cache_data_left() const; - mutable Error last_error; - -protected: - Error set_error(Error p_error) const; - - mutable struct File { - bool open = false; - int size = 0; - int offset = 0; - String name; - int access_flags = 0; - } file; - - mutable struct Cache { - Vector<uint8_t> buffer; - int offset = 0; - } cache; + struct Pair { + TKey key; + TData data; + + Pair() {} + Pair(const TKey &p_key, const TData &p_data) : + key(p_key), + data(p_data) { + } + }; - virtual int read_data_block(int p_offset, int p_size, uint8_t *p_dest = nullptr) const = 0; + typedef typename List<Pair>::Element *Element; - void set_cache_size(int p_size); - int get_cache_size(); + List<Pair> _list; + HashMap<TKey, Element> _map; + size_t capacity; public: - virtual size_t get_position() const; ///< get position in the file - virtual size_t get_len() const; ///< get size of the file - - virtual void seek(size_t p_position); ///< seek to a given position - virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file - - virtual bool eof_reached() const; - - virtual uint8_t get_8() const; - virtual int get_buffer(uint8_t *p_dest, int p_length) const; ///< get an array of bytes - - virtual bool is_open() const; - - virtual Error get_error() const; + const TData *insert(const TKey &p_key, const TData &p_value) { + Element *e = _map.getptr(p_key); + Element n = _list.push_front(Pair(p_key, p_value)); + + if (e) { + _list.erase(*e); + _map.erase(p_key); + } + _map[p_key] = _list.front(); + + while (_map.size() > capacity) { + Element d = _list.back(); + _map.erase(d->get().key); + _list.pop_back(); + } + + return &n->get().data; + } + + void clear() { + _map.clear(); + _list.clear(); + } + + bool has(const TKey &p_key) const { + return _map.getptr(p_key); + } + + const TData &get(const TKey &p_key) { + Element *e = _map.getptr(p_key); + CRASH_COND(!e); + _list.move_to_front(*e); + return (*e)->get().data; + }; - FileAccessBuffered() {} - virtual ~FileAccessBuffered() {} + const TData *getptr(const TKey &p_key) { + Element *e = _map.getptr(p_key); + if (!e) { + return nullptr; + } else { + _list.move_to_front(*e); + return &(*e)->get().data; + } + } + + _FORCE_INLINE_ size_t get_capacity() const { return capacity; } + + void set_capacity(size_t p_capacity) { + if (capacity > 0) { + capacity = p_capacity; + while (_map.size() > capacity) { + Element d = _list.back(); + _map.erase(d->get().key); + _list.pop_back(); + } + } + } + + LRUCache() { + capacity = 64; + } + + LRUCache(int p_capacity) { + capacity = p_capacity; + } }; #endif diff --git a/core/map.h b/core/templates/map.h index fd4f500556..51a237472d 100644 --- a/core/map.h +++ b/core/templates/map.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef MAP_H #define MAP_H -#include "core/error_macros.h" -#include "core/set.h" +#include "core/error/error_macros.h" +#include "core/templates/set.h" // based on the very nice implementation of rb-trees by: // https://web.archive.org/web/20120507164830/http://web.mit.edu/~emin/www/source_code/red_black_tree/index.html @@ -625,7 +625,7 @@ public: return e; } - inline bool empty() const { return _data.size_cache == 0; } + inline bool is_empty() const { return _data.size_cache == 0; } inline int size() const { return _data.size_cache; } int calculate_depth() const { diff --git a/core/oa_hash_map.h b/core/templates/oa_hash_map.h index 6061366ab3..1d4176eb10 100644 --- a/core/oa_hash_map.h +++ b/core/templates/oa_hash_map.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,10 +31,10 @@ #ifndef OA_HASH_MAP_H #define OA_HASH_MAP_H -#include "core/hashfuncs.h" #include "core/math/math_funcs.h" #include "core/os/copymem.h" #include "core/os/memory.h" +#include "core/templates/hashfuncs.h" /** * A HashMap implementation that uses open addressing with Robin Hood hashing. @@ -190,7 +190,7 @@ public: _FORCE_INLINE_ uint32_t get_capacity() const { return capacity; } _FORCE_INLINE_ uint32_t get_num_elements() const { return num_elements; } - bool empty() const { + bool is_empty() const { return num_elements == 0; } diff --git a/core/ordered_hash_map.h b/core/templates/ordered_hash_map.h index e6a6340a2f..7a17eeb644 100644 --- a/core/ordered_hash_map.h +++ b/core/templates/ordered_hash_map.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +31,9 @@ #ifndef ORDERED_HASH_MAP_H #define ORDERED_HASH_MAP_H -#include "core/hash_map.h" -#include "core/list.h" -#include "core/pair.h" +#include "core/templates/hash_map.h" +#include "core/templates/list.h" +#include "core/templates/pair.h" /** * A hash map which allows to iterate elements in insertion order. @@ -265,7 +265,7 @@ public: return ConstElement(list.back()); } - inline bool empty() const { return list.empty(); } + inline bool is_empty() const { return list.is_empty(); } inline int size() const { return list.size(); } const void *id() const { diff --git a/core/templates/paged_allocator.h b/core/templates/paged_allocator.h new file mode 100644 index 0000000000..7002034710 --- /dev/null +++ b/core/templates/paged_allocator.h @@ -0,0 +1,129 @@ +/*************************************************************************/ +/* paged_allocator.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PAGED_ALLOCATOR_H +#define PAGED_ALLOCATOR_H + +#include "core/os/memory.h" +#include "core/os/spin_lock.h" +#include "core/typedefs.h" + +template <class T, bool thread_safe = false> +class PagedAllocator { + T **page_pool = nullptr; + T ***available_pool = nullptr; + uint32_t pages_allocated = 0; + uint32_t allocs_available = 0; + + uint32_t page_shift = 0; + uint32_t page_mask = 0; + uint32_t page_size = 0; + SpinLock spin_lock; + +public: + T *alloc() { + if (thread_safe) { + spin_lock.lock(); + } + if (unlikely(allocs_available == 0)) { + uint32_t pages_used = pages_allocated; + + pages_allocated++; + page_pool = (T **)memrealloc(page_pool, sizeof(T *) * pages_allocated); + available_pool = (T ***)memrealloc(available_pool, sizeof(T **) * pages_allocated); + + page_pool[pages_used] = (T *)memalloc(sizeof(T) * page_size); + available_pool[pages_used] = (T **)memalloc(sizeof(T *) * page_size); + + for (uint32_t i = 0; i < page_size; i++) { + available_pool[0][i] = &page_pool[pages_used][i]; + } + allocs_available += page_size; + } + + allocs_available--; + T *alloc = available_pool[allocs_available >> page_shift][allocs_available & page_mask]; + if (thread_safe) { + spin_lock.unlock(); + } + memnew_placement(alloc, T); + return alloc; + } + + void free(T *p_mem) { + if (thread_safe) { + spin_lock.lock(); + } + p_mem->~T(); + available_pool[allocs_available >> page_shift][allocs_available & page_mask] = p_mem; + if (thread_safe) { + spin_lock.unlock(); + } + allocs_available++; + } + + void reset() { + ERR_FAIL_COND(allocs_available < pages_allocated * page_size); + if (pages_allocated) { + for (uint32_t i = 0; i < pages_allocated; i++) { + memfree(page_pool[i]); + memfree(available_pool[i]); + } + memfree(page_pool); + memfree(available_pool); + page_pool = nullptr; + available_pool = nullptr; + pages_allocated = 0; + allocs_available = 0; + } + } + bool is_configured() const { + return page_size > 0; + } + + void configure(uint32_t p_page_size) { + ERR_FAIL_COND(page_pool != nullptr); //sanity check + ERR_FAIL_COND(p_page_size == 0); + page_size = nearest_power_of_2_templated(p_page_size); + page_mask = page_size - 1; + page_shift = get_shift_from_power_of_2(page_size); + } + + PagedAllocator(uint32_t p_page_size = 4096) { // power of 2 recommended because of alignment with OS page sizes. Even if element is bigger, its still a multiple and get rounded amount of pages + configure(p_page_size); + } + + ~PagedAllocator() { + ERR_FAIL_COND_MSG(allocs_available < pages_allocated * page_size, "Pages in use exist at exit in PagedAllocator"); + reset(); + } +}; + +#endif // PAGED_ALLOCATOR_H diff --git a/core/templates/paged_array.h b/core/templates/paged_array.h new file mode 100644 index 0000000000..599d3dde4f --- /dev/null +++ b/core/templates/paged_array.h @@ -0,0 +1,367 @@ +/*************************************************************************/ +/* paged_array.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PAGED_ARRAY_H +#define PAGED_ARRAY_H + +#include "core/os/memory.h" +#include "core/os/spin_lock.h" +#include "core/typedefs.h" + +// PagedArray is used mainly for filling a very large array from multiple threads efficiently and without causing major fragmentation + +// PageArrayPool manages central page allocation in a thread safe matter + +template <class T> +class PagedArrayPool { + T **page_pool = nullptr; + uint32_t pages_allocated = 0; + + uint32_t *available_page_pool = nullptr; + uint32_t pages_available = 0; + + uint32_t page_size = 0; + SpinLock spin_lock; + +public: + uint32_t alloc_page() { + spin_lock.lock(); + if (unlikely(pages_available == 0)) { + uint32_t pages_used = pages_allocated; + + pages_allocated++; + page_pool = (T **)memrealloc(page_pool, sizeof(T *) * pages_allocated); + available_page_pool = (uint32_t *)memrealloc(available_page_pool, sizeof(uint32_t) * pages_allocated); + + page_pool[pages_used] = (T *)memalloc(sizeof(T) * page_size); + available_page_pool[0] = pages_used; + + pages_available++; + } + + pages_available--; + uint32_t page = available_page_pool[pages_available]; + spin_lock.unlock(); + + return page; + } + T *get_page(uint32_t p_page_id) { + return page_pool[p_page_id]; + } + + void free_page(uint32_t p_page_id) { + spin_lock.lock(); + available_page_pool[pages_available] = p_page_id; + pages_available++; + spin_lock.unlock(); + } + + uint32_t get_page_size_shift() const { + return get_shift_from_power_of_2(page_size); + } + + uint32_t get_page_size_mask() const { + return page_size - 1; + } + + void reset() { + ERR_FAIL_COND(pages_available < pages_allocated); + if (pages_allocated) { + for (uint32_t i = 0; i < pages_allocated; i++) { + memfree(page_pool[i]); + } + memfree(page_pool); + memfree(available_page_pool); + page_pool = nullptr; + available_page_pool = nullptr; + pages_allocated = 0; + pages_available = 0; + } + } + bool is_configured() const { + return page_size > 0; + } + + void configure(uint32_t p_page_size) { + ERR_FAIL_COND(page_pool != nullptr); //sanity check + ERR_FAIL_COND(p_page_size == 0); + page_size = nearest_power_of_2_templated(p_page_size); + } + + PagedArrayPool(uint32_t p_page_size = 4096) { // power of 2 recommended because of alignment with OS page sizes. Even if element is bigger, its still a multiple and get rounded amount of pages + configure(p_page_size); + } + + ~PagedArrayPool() { + ERR_FAIL_COND_MSG(pages_available < pages_allocated, "Pages in use exist at exit in PagedArrayPool"); + reset(); + } +}; + +// PageArray is a local array that is optimized to grow in place, then be cleared often. +// It does so by allocating pages from a PagedArrayPool. +// It is safe to use multiple PagedArrays from different threads, sharing a single PagedArrayPool + +template <class T> +class PagedArray { + PagedArrayPool<T> *page_pool = nullptr; + + T **page_data = nullptr; + uint32_t *page_ids = nullptr; + uint32_t max_pages_used = 0; + uint32_t page_size_shift = 0; + uint32_t page_size_mask = 0; + uint64_t count = 0; + + _FORCE_INLINE_ uint32_t _get_pages_in_use() const { + if (count == 0) { + return 0; + } else { + return ((count - 1) >> page_size_shift) + 1; + } + } + + void _grow_page_array() { + //no more room in the page array to put the new page, make room + if (max_pages_used == 0) { + max_pages_used = 1; + } else { + max_pages_used *= 2; // increase in powers of 2 to keep allocations to minimum + } + page_data = (T **)memrealloc(page_data, sizeof(T *) * max_pages_used); + page_ids = (uint32_t *)memrealloc(page_ids, sizeof(uint32_t) * max_pages_used); + } + +public: + _FORCE_INLINE_ const T &operator[](uint64_t p_index) const { + CRASH_BAD_UNSIGNED_INDEX(p_index, count); + uint32_t page = p_index >> page_size_shift; + uint32_t offset = p_index & page_size_mask; + + return page_data[page][offset]; + } + _FORCE_INLINE_ T &operator[](uint64_t p_index) { + CRASH_BAD_UNSIGNED_INDEX(p_index, count); + uint32_t page = p_index >> page_size_shift; + uint32_t offset = p_index & page_size_mask; + + return page_data[page][offset]; + } + + _FORCE_INLINE_ void push_back(const T &p_value) { + uint32_t remainder = count & page_size_mask; + if (unlikely(remainder == 0)) { + // at 0, so time to request a new page + uint32_t page_count = _get_pages_in_use(); + uint32_t new_page_count = page_count + 1; + + if (unlikely(new_page_count > max_pages_used)) { + ERR_FAIL_COND(page_pool == nullptr); //sanity check + + _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; + } + + // place the new value + uint32_t page = count >> page_size_shift; + uint32_t offset = count & page_size_mask; + + if (!__has_trivial_constructor(T)) { + memnew_placement(&page_data[page][offset], T(p_value)); + } else { + page_data[page][offset] = p_value; + } + + count++; + } + + _FORCE_INLINE_ void pop_back() { + ERR_FAIL_COND(count == 0); + + if (!__has_trivial_destructor(T)) { + uint32_t page = (count - 1) >> page_size_shift; + uint32_t offset = (count - 1) & page_size_mask; + page_data[page][offset].~T(); + } + + uint32_t remainder = count & page_size_mask; + if (unlikely(remainder == 1)) { + // one element remained, so page must be freed. + uint32_t last_page = _get_pages_in_use() - 1; + page_pool->free_page(page_ids[last_page]); + } + count--; + } + + void clear() { + //destruct if needed + if (!__has_trivial_destructor(T)) { + for (uint64_t i = 0; i < count; i++) { + uint32_t page = i >> page_size_shift; + uint32_t offset = i & page_size_mask; + page_data[page][offset].~T(); + } + } + + //return the pages to the pagepool, so they can be used by another array eventually + uint32_t pages_used = _get_pages_in_use(); + for (uint32_t i = 0; i < pages_used; i++) { + page_pool->free_page(page_ids[i]); + } + + count = 0; + + //note we leave page_data and page_indices intact for next use. If you really want to clear them call reset() + } + + void reset() { + clear(); + if (page_data) { + memfree(page_data); + memfree(page_ids); + page_data = nullptr; + page_ids = nullptr; + max_pages_used = 0; + } + } + + // This takes the pages from a source array and merges them to this one + // resulting order is undefined, but content is merged very efficiently, + // making it ideal to fill content on several threads to later join it. + + void merge_unordered(PagedArray<T> &p_array) { + ERR_FAIL_COND(page_pool != p_array.page_pool); + + uint32_t remainder = count & page_size_mask; + + T *remainder_page = nullptr; + uint32_t remainder_page_id; + + if (remainder > 0) { + uint32_t last_page = _get_pages_in_use() - 1; + remainder_page = page_data[last_page]; + remainder_page_id = page_ids[last_page]; + } + + count -= remainder; + + uint32_t src_pages = p_array._get_pages_in_use(); + uint32_t page_size = page_size_mask + 1; + + for (uint32_t i = 0; i < src_pages; i++) { + uint32_t page_count = _get_pages_in_use(); + uint32_t new_page_count = page_count + 1; + + if (unlikely(new_page_count > max_pages_used)) { + _grow_page_array(); //keep out of inline + } + + page_data[page_count] = p_array.page_data[i]; + page_ids[page_count] = p_array.page_ids[i]; + if (i == src_pages - 1) { + //last page, only increment with remainder + count += p_array.count & page_size_mask; + } else { + count += page_size; + } + } + p_array.count = 0; //take away the other array pages + + //handle the remainder page if exists + if (remainder_page) { + uint32_t new_remainder = count & page_size_mask; + + if (new_remainder > 0) { + //must merge old remainder with new remainder + + T *dst_page = page_data[_get_pages_in_use() - 1]; + uint32_t to_copy = MIN(page_size - new_remainder, remainder); + + for (uint32_t i = 0; i < to_copy; i++) { + if (!__has_trivial_constructor(T)) { + memnew_placement(&dst_page[i + new_remainder], T(remainder_page[i + remainder - to_copy])); + } else { + dst_page[i + new_remainder] = remainder_page[i + remainder - to_copy]; + } + + if (!__has_trivial_destructor(T)) { + remainder_page[i + remainder - to_copy].~T(); + } + } + + remainder -= to_copy; //subtract what was copied from remainder + count += to_copy; //add what was copied to the count + + if (remainder == 0) { + //entire remainder copied, let go of remainder page + page_pool->free_page(remainder_page_id); + remainder_page = nullptr; + } + } + + if (remainder > 0) { + //there is still remainder, append it + uint32_t page_count = _get_pages_in_use(); + uint32_t new_page_count = page_count + 1; + + if (unlikely(new_page_count > max_pages_used)) { + _grow_page_array(); //keep out of inline + } + + page_data[page_count] = remainder_page; + page_ids[page_count] = remainder_page_id; + + count += remainder; + } + } + } + + _FORCE_INLINE_ uint64_t size() const { + return count; + } + + void set_page_pool(PagedArrayPool<T> *p_page_pool) { + ERR_FAIL_COND(max_pages_used > 0); //sanity check + + page_pool = p_page_pool; + page_size_mask = page_pool->get_page_size_mask(); + page_size_shift = page_pool->get_page_size_shift(); + } + + ~PagedArray() { + reset(); + } +}; + +#endif // PAGED_ARRAY_H diff --git a/core/pair.h b/core/templates/pair.h index 89ea2b9fd9..bc1a764694 100644 --- a/core/pair.h +++ b/core/templates/pair.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/templates/pass_func.h b/core/templates/pass_func.h new file mode 100644 index 0000000000..d2f465e91c --- /dev/null +++ b/core/templates/pass_func.h @@ -0,0 +1,100 @@ +/*************************************************************************/ +/* pass_func.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PASS_FUNC_H +#define PASS_FUNC_H + +#define PASS0R(m_r, m_name) \ + m_r m_name() { return PASSBASE->m_name(); } +#define PASS0RC(m_r, m_name) \ + m_r m_name() const { return PASSBASE->m_name(); } +#define PASS1R(m_r, m_name, m_type1) \ + m_r m_name(m_type1 arg1) { return PASSBASE->m_name(arg1); } +#define PASS1RC(m_r, m_name, m_type1) \ + m_r m_name(m_type1 arg1) const { return PASSBASE->m_name(arg1); } +#define PASS2R(m_r, m_name, m_type1, m_type2) \ + m_r m_name(m_type1 arg1, m_type2 arg2) { return PASSBASE->m_name(arg1, arg2); } +#define PASS2RC(m_r, m_name, m_type1, m_type2) \ + m_r m_name(m_type1 arg1, m_type2 arg2) const { return PASSBASE->m_name(arg1, arg2); } +#define PASS3R(m_r, m_name, m_type1, m_type2, m_type3) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) { return PASSBASE->m_name(arg1, arg2, arg3); } +#define PASS3RC(m_r, m_name, m_type1, m_type2, m_type3) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) const { return PASSBASE->m_name(arg1, arg2, arg3); } +#define PASS4R(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { return PASSBASE->m_name(arg1, arg2, arg3, arg4); } +#define PASS4RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) const { return PASSBASE->m_name(arg1, arg2, arg3, arg4); } +#define PASS5R(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) { return PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5); } +#define PASS5RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) const { return PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5); } +#define PASS6R(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) { return PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); } +#define PASS6RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) const { return PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); } + +#define PASS0(m_name) \ + void m_name() { PASSBASE->m_name(); } +#define PASS1(m_name, m_type1) \ + void m_name(m_type1 arg1) { PASSBASE->m_name(arg1); } +#define PASS1C(m_name, m_type1) \ + void m_name(m_type1 arg1) const { PASSBASE->m_name(arg1); } +#define PASS2(m_name, m_type1, m_type2) \ + void m_name(m_type1 arg1, m_type2 arg2) { PASSBASE->m_name(arg1, arg2); } +#define PASS2C(m_name, m_type1, m_type2) \ + void m_name(m_type1 arg1, m_type2 arg2) const { PASSBASE->m_name(arg1, arg2); } +#define PASS3(m_name, m_type1, m_type2, m_type3) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) { PASSBASE->m_name(arg1, arg2, arg3); } +#define PASS4(m_name, m_type1, m_type2, m_type3, m_type4) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { PASSBASE->m_name(arg1, arg2, arg3, arg4); } +#define PASS5(m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5); } +#define PASS6(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); } +#define PASS7(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7); } +#define PASS8(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } +#define PASS9(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } +#define PASS10(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); } +#define PASS11(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); } +#define PASS12(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); } +#define PASS13(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); } +#define PASS14(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); } +#define PASS15(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14, m_type15) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14, m_type15 arg15) { PASSBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); } + +#endif // PASS_FUNC_H diff --git a/core/rid.h b/core/templates/rid.h index 4b65f3fb6a..7fe6dbe473 100644 --- a/core/rid.h +++ b/core/templates/rid.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -52,6 +52,9 @@ public: _FORCE_INLINE_ bool operator>(const RID &p_rid) const { return _id > p_rid._id; } + _FORCE_INLINE_ bool operator>=(const RID &p_rid) const { + return _id >= p_rid._id; + } _FORCE_INLINE_ bool operator!=(const RID &p_rid) const { return _id != p_rid._id; } diff --git a/core/rid_owner.cpp b/core/templates/rid_owner.cpp index a5065f29f8..f75a2eb9df 100644 --- a/core/rid_owner.cpp +++ b/core/templates/rid_owner.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/rid_owner.h b/core/templates/rid_owner.h index 30f1e41733..d26c445eb4 100644 --- a/core/rid_owner.h +++ b/core/templates/rid_owner.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,14 +31,14 @@ #ifndef RID_OWNER_H #define RID_OWNER_H -#include "core/list.h" -#include "core/oa_hash_map.h" #include "core/os/memory.h" -#include "core/print_string.h" -#include "core/rid.h" -#include "core/safe_refcount.h" -#include "core/set.h" -#include "core/spin_lock.h" +#include "core/os/spin_lock.h" +#include "core/string/print_string.h" +#include "core/templates/list.h" +#include "core/templates/oa_hash_map.h" +#include "core/templates/rid.h" +#include "core/templates/safe_refcount.h" +#include "core/templates/set.h" #include <stdio.h> #include <typeinfo> @@ -346,6 +346,18 @@ public: alloc.free(p_rid); } + _FORCE_INLINE_ uint32_t get_rid_count() const { + return alloc.get_rid_count(); + } + + _FORCE_INLINE_ RID get_rid_by_index(uint32_t p_index) { + return alloc.get_rid_by_index(p_index); + } + + _FORCE_INLINE_ T *get_ptr_by_index(uint32_t p_index) { + return *alloc.get_ptr_by_index(p_index); + } + _FORCE_INLINE_ void get_owned_list(List<RID> *p_owned) { return alloc.get_owned_list(p_owned); } @@ -353,6 +365,7 @@ public: void set_description(const char *p_descrption) { alloc.set_description(p_descrption); } + RID_PtrOwner(uint32_t p_target_chunk_byte_size = 4096) : alloc(p_target_chunk_byte_size) {} }; diff --git a/core/ring_buffer.h b/core/templates/ring_buffer.h index 6b71d12cf3..e7b77440f1 100644 --- a/core/ring_buffer.h +++ b/core/templates/ring_buffer.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef RING_BUFFER_H #define RING_BUFFER_H -#include "core/vector.h" +#include "core/templates/vector.h" template <typename T> class RingBuffer { diff --git a/core/safe_refcount.cpp b/core/templates/safe_refcount.cpp index d5ee778ef7..a915ee662f 100644 --- a/core/safe_refcount.cpp +++ b/core/templates/safe_refcount.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/safe_refcount.h b/core/templates/safe_refcount.h index dc4e62354a..d94444fad6 100644 --- a/core/safe_refcount.h +++ b/core/templates/safe_refcount.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -165,7 +165,7 @@ uint64_t atomic_exchange_if_greater(volatile uint64_t *pw, volatile uint64_t val #endif struct SafeRefCount { - uint32_t count; + uint32_t count = 0; public: // destroy() is called when weak_count_ drops to zero. diff --git a/core/self_list.h b/core/templates/self_list.h index 3104bcb714..e8d36ea358 100644 --- a/core/self_list.h +++ b/core/templates/self_list.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef SELF_LIST_H #define SELF_LIST_H -#include "core/error_macros.h" +#include "core/error/error_macros.h" #include "core/typedefs.h" template <class T> diff --git a/core/set.h b/core/templates/set.h index 1bc0a3f41e..3036ecf27d 100644 --- a/core/set.h +++ b/core/templates/set.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -80,7 +80,7 @@ public: private: struct _Data { Element *_root = nullptr; - Element *_nil; + Element *_nil = nullptr; int size_cache = 0; _FORCE_INLINE_ _Data() { @@ -576,7 +576,7 @@ public: return e; } - inline bool empty() const { return _data.size_cache == 0; } + inline bool is_empty() const { return _data.size_cache == 0; } inline int size() const { return _data.size_cache; } int calculate_depth() const { diff --git a/core/simple_type.h b/core/templates/simple_type.h index 10dc36cbd4..80bfa83fde 100644 --- a/core/simple_type.h +++ b/core/templates/simple_type.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -48,4 +48,9 @@ struct GetSimpleTypeT<T const> { typedef T type_t; }; +template <class T> +struct GetSimpleTypeT<T const &> { + typedef T type_t; +}; + #endif // SIMPLE_TYPE_H diff --git a/core/sort_array.h b/core/templates/sort_array.h index 93cc6f727d..1656d2991d 100644 --- a/core/sort_array.h +++ b/core/templates/sort_array.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef SORT_ARRAY_H #define SORT_ARRAY_H -#include "core/error_macros.h" +#include "core/error/error_macros.h" #include "core/typedefs.h" #define ERR_BAD_COMPARE(cond) \ @@ -54,7 +54,6 @@ struct _DefaultComparator { template <class T, class Comparator = _DefaultComparator<T>, bool Validate = SORT_ARRAY_VALIDATE_ENABLED> class SortArray { enum { - INTROSORT_THRESHOLD = 16 }; diff --git a/core/thread_work_pool.cpp b/core/templates/thread_work_pool.cpp index 3a95e83ffc..ea784e510c 100644 --- a/core/thread_work_pool.cpp +++ b/core/templates/thread_work_pool.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/thread_work_pool.h b/core/templates/thread_work_pool.h index 661060aa3f..02d941d0f4 100644 --- a/core/thread_work_pool.h +++ b/core/templates/thread_work_pool.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -41,8 +41,8 @@ class ThreadWorkPool { std::atomic<uint32_t> index; struct BaseWork { - std::atomic<uint32_t> *index; - uint32_t max_elements; + std::atomic<uint32_t> *index = nullptr; + uint32_t max_elements = 0; virtual void work() = 0; virtual ~BaseWork() = default; }; diff --git a/core/vector.h b/core/templates/vector.h index 5a61f0eae3..6a8902707c 100644 --- a/core/vector.h +++ b/core/templates/vector.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,11 +37,11 @@ * Vector container. Regular Vector Container. Use with care and for smaller arrays when possible. Use Vector for large arrays. */ -#include "core/cowdata.h" -#include "core/error_macros.h" +#include "core/error/error_macros.h" #include "core/os/copymem.h" #include "core/os/memory.h" -#include "core/sort_array.h" +#include "core/templates/cowdata.h" +#include "core/templates/sort_array.h" template <class T> class VectorWriteProxy { @@ -79,7 +79,7 @@ public: _FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); } _FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); } _FORCE_INLINE_ void clear() { resize(0); } - _FORCE_INLINE_ bool empty() const { return _cowdata.empty(); } + _FORCE_INLINE_ bool is_empty() const { return _cowdata.is_empty(); } _FORCE_INLINE_ T get(int p_index) { return _cowdata.get(p_index); } _FORCE_INLINE_ const T &get(int p_index) const { return _cowdata.get(p_index); } @@ -112,6 +112,10 @@ public: sort_custom<_DefaultComparator<T>>(); } + Vector<T> duplicate() { + return *this; + } + void ordered_insert(const T &p_val) { int i; for (i = 0; i < _cowdata.size(); i++) { @@ -157,6 +161,32 @@ public: return slice; } + bool operator==(const Vector<T> &p_arr) const { + int s = size(); + if (s != p_arr.size()) { + return false; + } + for (int i = 0; i < s; i++) { + if (operator[](i) != p_arr[i]) { + return false; + } + } + return true; + } + + bool operator!=(const Vector<T> &p_arr) const { + int s = size(); + if (s != p_arr.size()) { + return true; + } + for (int i = 0; i < s; i++) { + if (operator[](i) != p_arr[i]) { + return true; + } + } + return false; + } + _FORCE_INLINE_ Vector() {} _FORCE_INLINE_ Vector(const Vector &p_from) { _cowdata._ref(p_from._cowdata); } diff --git a/core/vmap.h b/core/templates/vmap.h index c91ea9b3c9..520e0b3720 100644 --- a/core/vmap.h +++ b/core/templates/vmap.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef VMAP_H #define VMAP_H -#include "core/cowdata.h" +#include "core/templates/cowdata.h" #include "core/typedefs.h" template <class T, class V> @@ -54,7 +54,7 @@ private: _FORCE_INLINE_ int _find(const T &p_val, bool &r_exact) const { r_exact = false; - if (_cowdata.empty()) { + if (_cowdata.is_empty()) { return 0; } @@ -89,7 +89,7 @@ private: } _FORCE_INLINE_ int _find_exact(const T &p_val) const { - if (_cowdata.empty()) { + if (_cowdata.is_empty()) { return -1; } @@ -147,7 +147,7 @@ public: } _FORCE_INLINE_ int size() const { return _cowdata.size(); } - _FORCE_INLINE_ bool empty() const { return _cowdata.empty(); } + _FORCE_INLINE_ bool is_empty() const { return _cowdata.is_empty(); } const Pair *get_array() const { return _cowdata.ptr(); diff --git a/core/vset.h b/core/templates/vset.h index 034b8fe851..6665651d42 100644 --- a/core/vset.h +++ b/core/templates/vset.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef VSET_H #define VSET_H +#include "core/templates/vector.h" #include "core/typedefs.h" -#include "core/vector.h" template <class T> class VSet { @@ -40,7 +40,7 @@ class VSet { _FORCE_INLINE_ int _find(const T &p_val, bool &r_exact) const { r_exact = false; - if (_data.empty()) { + if (_data.is_empty()) { return 0; } @@ -76,7 +76,7 @@ class VSet { } _FORCE_INLINE_ int _find_exact(const T &p_val) const { - if (_data.empty()) { + if (_data.is_empty()) { return -1; } @@ -126,7 +126,7 @@ public: return _find_exact(p_val); } - _FORCE_INLINE_ bool empty() const { return _data.empty(); } + _FORCE_INLINE_ bool is_empty() const { return _data.is_empty(); } _FORCE_INLINE_ int size() const { return _data.size(); } diff --git a/core/typedefs.h b/core/typedefs.h index 4bfa5debac..cdbfb34e56 100644 --- a/core/typedefs.h +++ b/core/typedefs.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -41,8 +41,8 @@ #include "platform_config.h" // Should be available everywhere. -#include "core/error_list.h" -#include "core/int_types.h" +#include "core/error/error_list.h" +#include <cstdint> // Turn argument to string constant: // https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html#Stringizing @@ -92,7 +92,7 @@ #endif #ifndef SGN -#define SGN(m_v) (((m_v) < 0) ? (-1.0) : (+1.0)) +#define SGN(m_v) (((m_v) == 0) ? (0.0) : (((m_v) < 0) ? (-1.0) : (+1.0))) #endif #ifndef MIN @@ -193,6 +193,20 @@ static inline unsigned int nearest_shift(unsigned int p_number) { return 0; } +// constexpr function to find the floored log2 of a number +template <typename T> +constexpr T floor_log2(T x) { + return x < 2 ? x : 1 + floor_log2(x >> 1); +} + +// Get the number of bits needed to represent the number. +// IE, if you pass in 8, you will get 4. +// If you want to know how many bits are needed to store 8 values however, pass in (8 - 1). +template <typename T> +constexpr T get_num_bits(T x) { + return floor_log2(x); +} + // Swap 16, 32 and 64 bits value for endianness. #if defined(__GNUC__) #define BSWAP16(x) __builtin_bswap16(x) @@ -263,4 +277,8 @@ struct BuildIndexSequence : BuildIndexSequence<N - 1, N - 1, Is...> {}; template <size_t... Is> struct BuildIndexSequence<0, Is...> : IndexSequence<Is...> {}; +#ifdef DEBUG_ENABLED +#define DEBUG_METHODS_ENABLED +#endif + #endif // TYPEDEFS_H diff --git a/core/variant/SCsub b/core/variant/SCsub new file mode 100644 index 0000000000..7f4c8b7788 --- /dev/null +++ b/core/variant/SCsub @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +Import("env") + +env_variant = env.Clone() + +env_variant.add_source_files(env.core_sources, "*.cpp") diff --git a/core/array.cpp b/core/variant/array.cpp index d1c0688e63..48916f941e 100644 --- a/core/array.cpp +++ b/core/variant/array.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,11 +31,11 @@ #include "array.h" #include "container_type_validate.h" -#include "core/hashfuncs.h" -#include "core/object.h" -#include "core/script_language.h" -#include "core/variant.h" -#include "core/vector.h" +#include "core/object/class_db.h" +#include "core/object/script_language.h" +#include "core/templates/hashfuncs.h" +#include "core/templates/vector.h" +#include "core/variant/variant.h" class ArrayPrivate { public: @@ -86,8 +86,8 @@ int Array::size() const { return _p->array.size(); } -bool Array::empty() const { - return _p->array.empty(); +bool Array::is_empty() const { + return _p->array.is_empty(); } void Array::clear() { @@ -98,6 +98,37 @@ bool Array::operator==(const Array &p_array) const { return _p == p_array._p; } +bool Array::operator!=(const Array &p_array) const { + return !operator==(p_array); +} + +bool Array::operator<(const Array &p_array) const { + int a_len = size(); + int b_len = p_array.size(); + + int min_cmp = MIN(a_len, b_len); + + for (int i = 0; i < min_cmp; i++) { + if (operator[](i) < p_array[i]) { + return true; + } else if (p_array[i] < operator[](i)) { + return false; + } + } + + return a_len < b_len; +} + +bool Array::operator<=(const Array &p_array) const { + return !operator>(p_array); +} +bool Array::operator>(const Array &p_array) const { + return p_array < *this; +} +bool Array::operator>=(const Array &p_array) const { + return !operator<(p_array); +} + uint32_t Array::hash() const { uint32_t h = hash_djb2_one_32(0); @@ -134,7 +165,7 @@ void Array::_assign(const Array &p_array) { } else if (Variant::can_convert_strict(src_val.get_type(), _p->typed.type)) { Variant *ptr = &src_val; Callable::CallError ce; - new_array.write[i] = Variant::construct(_p->typed.type, (const Variant **)&ptr, 1, ce, true); + Variant::construct(_p->typed.type, new_array.write[i], (const Variant **)&ptr, 1, ce); if (ce.error != Callable::CallError::CALL_OK) { ERR_FAIL_MSG("Unable to convert array index " + itos(i) + " from '" + Variant::get_type_name(src_val.get_type()) + "' to '" + Variant::get_type_name(_p->typed.type) + "'."); } @@ -161,6 +192,11 @@ void Array::push_back(const Variant &p_value) { _p->array.push_back(p_value); } +void Array::append_array(const Array &p_array) { + ERR_FAIL_COND(!_p->typed.validate(p_array, "append_array")); + _p->array.append_array(p_array._p->array); +} + Error Array::resize(int p_new_size) { return _p->array.resize(p_new_size); } @@ -282,7 +318,7 @@ Array Array::slice(int p_begin, int p_end, int p_step, bool p_deep) const { // l ERR_FAIL_COND_V_MSG(p_step == 0, new_arr, "Array slice step size cannot be zero."); - if (empty()) { // Don't try to slice empty arrays. + if (is_empty()) { // Don't try to slice empty arrays. return new_arr; } if (p_step > 0) { @@ -330,13 +366,12 @@ struct _ArrayVariantSort { } }; -Array &Array::sort() { +void Array::sort() { _p->array.sort_custom<_ArrayVariantSort>(); - return *this; } struct _ArrayVariantSortCustom { - Object *obj; + Object *obj = nullptr; StringName func; _FORCE_INLINE_ bool operator()(const Variant &p_l, const Variant &p_r) const { @@ -349,14 +384,13 @@ struct _ArrayVariantSortCustom { return res; } }; -Array &Array::sort_custom(Object *p_obj, const StringName &p_function) { - ERR_FAIL_NULL_V(p_obj, *this); +void Array::sort_custom(Object *p_obj, const StringName &p_function) { + ERR_FAIL_NULL(p_obj); SortArray<Variant, _ArrayVariantSortCustom, true> avs; avs.compare.obj = p_obj; avs.compare.func = p_function; avs.sort(_p->array.ptrw(), _p->array.size()); - return *this; } void Array::shuffle() { @@ -415,9 +449,8 @@ int Array::bsearch_custom(const Variant &p_value, Object *p_obj, const StringNam return bisect(_p->array, p_value, p_before, less); } -Array &Array::invert() { +void Array::invert() { _p->array.invert(); - return *this; } void Array::push_front(const Variant &p_value) { @@ -426,7 +459,7 @@ void Array::push_front(const Variant &p_value) { } Variant Array::pop_back() { - if (!_p->array.empty()) { + if (!_p->array.is_empty()) { int n = _p->array.size() - 1; Variant ret = _p->array.get(n); _p->array.resize(n); @@ -436,7 +469,7 @@ Variant Array::pop_back() { } Variant Array::pop_front() { - if (!_p->array.empty()) { + if (!_p->array.is_empty()) { Variant ret = _p->array.get(0); _p->array.remove(0); return ret; diff --git a/core/array.h b/core/variant/array.h index d2e0537ad5..26de5477b4 100644 --- a/core/array.h +++ b/core/variant/array.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -57,16 +57,18 @@ public: const Variant &get(int p_idx) const; int size() const; - bool empty() const; + bool is_empty() const; void clear(); bool operator==(const Array &p_array) const; + bool operator!=(const Array &p_array) const; uint32_t hash() const; void operator=(const Array &p_array); void push_back(const Variant &p_value); _FORCE_INLINE_ void append(const Variant &p_value) { push_back(p_value); } //for python compatibility + void append_array(const Array &p_array); Error resize(int p_new_size); void insert(int p_pos, const Variant &p_value); @@ -75,12 +77,12 @@ public: Variant front() const; Variant back() const; - Array &sort(); - Array &sort_custom(Object *p_obj, const StringName &p_function); + void sort(); + void sort_custom(Object *p_obj, const StringName &p_function); void shuffle(); int bsearch(const Variant &p_value, bool p_before = true); int bsearch_custom(const Variant &p_value, Object *p_obj, const StringName &p_function, bool p_before = true); - Array &invert(); + void invert(); int find(const Variant &p_value, int p_from = 0) const; int rfind(const Variant &p_value, int p_from = -1) const; @@ -98,6 +100,11 @@ public: Array slice(int p_begin, int p_end, int p_step = 1, bool p_deep = false) const; + bool operator<(const Array &p_array) const; + bool operator<=(const Array &p_array) const; + bool operator>(const Array &p_array) const; + bool operator>=(const Array &p_array) const; + Variant min() const; Variant max() const; diff --git a/core/variant/binder_common.h b/core/variant/binder_common.h new file mode 100644 index 0000000000..9d8e262cc9 --- /dev/null +++ b/core/variant/binder_common.h @@ -0,0 +1,666 @@ +/*************************************************************************/ +/* binder_common.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef BINDER_COMMON_H +#define BINDER_COMMON_H + +#include "core/object/object.h" +#include "core/templates/list.h" +#include "core/templates/simple_type.h" +#include "core/typedefs.h" +#include "core/variant/method_ptrcall.h" +#include "core/variant/type_info.h" +#include "core/variant/variant.h" +#include "core/variant/variant_internal.h" + +#include <stdio.h> + +template <class T> +struct VariantCaster { + static _FORCE_INLINE_ T cast(const Variant &p_variant) { + return p_variant; + } +}; + +template <class T> +struct VariantCaster<T &> { + static _FORCE_INLINE_ T cast(const Variant &p_variant) { + return p_variant; + } +}; + +template <class T> +struct VariantCaster<const T &> { + static _FORCE_INLINE_ T cast(const Variant &p_variant) { + return p_variant; + } +}; + +#define VARIANT_ENUM_CAST(m_enum) \ + MAKE_ENUM_TYPE_INFO(m_enum) \ + template <> \ + struct VariantCaster<m_enum> { \ + static _FORCE_INLINE_ m_enum cast(const Variant &p_variant) { \ + return (m_enum)p_variant.operator int(); \ + } \ + }; \ + template <> \ + struct PtrToArg<m_enum> { \ + _FORCE_INLINE_ static m_enum convert(const void *p_ptr) { \ + return m_enum(*reinterpret_cast<const int *>(p_ptr)); \ + } \ + _FORCE_INLINE_ static void encode(m_enum p_val, const void *p_ptr) { \ + *(int *)p_ptr = p_val; \ + } \ + }; + +// Object enum casts must go here +VARIANT_ENUM_CAST(Object::ConnectFlags); + +VARIANT_ENUM_CAST(Vector3::Axis); + +VARIANT_ENUM_CAST(Error); +VARIANT_ENUM_CAST(Side); +VARIANT_ENUM_CAST(Corner); +VARIANT_ENUM_CAST(Orientation); +VARIANT_ENUM_CAST(HAlign); +VARIANT_ENUM_CAST(VAlign); +VARIANT_ENUM_CAST(PropertyHint); +VARIANT_ENUM_CAST(PropertyUsageFlags); +VARIANT_ENUM_CAST(Variant::Type); +VARIANT_ENUM_CAST(Variant::Operator); + +template <> +struct VariantCaster<char32_t> { + static _FORCE_INLINE_ char32_t cast(const Variant &p_variant) { + return (char32_t)p_variant.operator int(); + } +}; + +template <> +struct PtrToArg<char32_t> { + _FORCE_INLINE_ static char32_t convert(const void *p_ptr) { + return char32_t(*reinterpret_cast<const int *>(p_ptr)); + } + _FORCE_INLINE_ static void encode(char32_t p_val, const void *p_ptr) { + *(int *)p_ptr = p_val; + } +}; + +template <typename T> +struct VariantObjectClassChecker { + static _FORCE_INLINE_ bool check(const Variant &p_variant) { + return true; + } +}; + +template <> +struct VariantObjectClassChecker<Node *> { + static _FORCE_INLINE_ bool check(const Variant &p_variant) { + Object *obj = p_variant; + Node *node = p_variant; + return node || !obj; + } +}; + +template <> +struct VariantObjectClassChecker<Control *> { + static _FORCE_INLINE_ bool check(const Variant &p_variant) { + Object *obj = p_variant; + Control *control = p_variant; + return control || !obj; + } +}; + +#ifdef DEBUG_METHODS_ENABLED + +template <class T> +struct VariantCasterAndValidate { + static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { + Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE; + if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) || + !VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = p_arg_idx; + r_error.expected = argtype; + } + + return VariantCaster<T>::cast(*p_args[p_arg_idx]); + } +}; + +template <class T> +struct VariantCasterAndValidate<T &> { + static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { + Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE; + if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) || + !VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = p_arg_idx; + r_error.expected = argtype; + } + + return VariantCaster<T>::cast(*p_args[p_arg_idx]); + } +}; + +template <class T> +struct VariantCasterAndValidate<const T &> { + static _FORCE_INLINE_ T cast(const Variant **p_args, uint32_t p_arg_idx, Callable::CallError &r_error) { + Variant::Type argtype = GetTypeInfo<T>::VARIANT_TYPE; + if (!Variant::can_convert_strict(p_args[p_arg_idx]->get_type(), argtype) || + !VariantObjectClassChecker<T>::check(p_args[p_arg_idx])) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = p_arg_idx; + r_error.expected = argtype; + } + + return VariantCaster<T>::cast(*p_args[p_arg_idx]); + } +}; + +#endif // DEBUG_METHODS_ENABLED + +template <class T, class... P, size_t... Is> +void call_with_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) { + r_error.error = Callable::CallError::CALL_OK; + +#ifdef DEBUG_METHODS_ENABLED + (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); +#else + (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...); +#endif + (void)(p_args); //avoid warning +} + +template <class T, class... P, size_t... Is> +void call_with_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) { + r_error.error = Callable::CallError::CALL_OK; + +#ifdef DEBUG_METHODS_ENABLED + (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); +#else + (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...); +#endif + (void)(p_args); //avoid warning +} + +template <class T, class... P, size_t... Is> +void call_with_ptr_args_helper(T *p_instance, void (T::*p_method)(P...), const void **p_args, IndexSequence<Is...>) { + (p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...); +} + +template <class T, class... P, size_t... Is> +void call_with_ptr_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const void **p_args, IndexSequence<Is...>) { + (p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...); +} + +template <class T, class R, class... P, size_t... Is> +void call_with_ptr_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const void **p_args, void *r_ret, IndexSequence<Is...>) { + PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret); +} + +template <class T, class R, class... P, size_t... Is> +void call_with_ptr_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const void **p_args, void *r_ret, IndexSequence<Is...>) { + PtrToArg<R>::encode((p_instance->*p_method)(PtrToArg<P>::convert(p_args[Is])...), r_ret); +} + +template <class T, class R, class... P, size_t... Is> +void call_with_ptr_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P...), const void **p_args, void *r_ret, IndexSequence<Is...>) { + PtrToArg<R>::encode(p_method(p_instance, PtrToArg<P>::convert(p_args[Is])...), r_ret); +} + +template <class T, class... P, size_t... Is> +void call_with_validated_variant_args_helper(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, IndexSequence<Is...>) { + (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); +} + +template <class T, class... P, size_t... Is> +void call_with_validated_variant_argsc_helper(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, IndexSequence<Is...>) { + (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...); +} + +template <class T, class R, class... P, size_t... Is> +void call_with_validated_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { + VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); +} + +template <class T, class R, class... P, size_t... Is> +void call_with_validated_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { + VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, (p_instance->*p_method)((VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); +} + +template <class T, class R, class... P, size_t... Is> +void call_with_validated_variant_args_static_retc_helper(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret, IndexSequence<Is...>) { + VariantInternalAccessor<typename GetSimpleTypeT<R>::type_t>::set(r_ret, p_method(p_instance, (VariantInternalAccessor<typename GetSimpleTypeT<P>::type_t>::get(p_args[Is]))...)); +} + +template <class T, class... P> +void call_with_variant_args(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +#ifdef DEBUG_METHODS_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } + + if ((size_t)p_argcount < sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class... P> +void call_with_variant_args_dv(T *p_instance, void (T::*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error, const Vector<Variant> &default_values) { +#ifdef DEBUG_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount; + + int32_t dvs = default_values.size(); +#ifdef DEBUG_ENABLED + if (missing > dvs) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array + for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) { + if (i < p_argcount) { + args[i] = p_args[i]; + } else { + args[i] = &default_values[i - p_argcount + (dvs - missing)]; + } + } + + call_with_variant_args_helper(p_instance, p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class... P> +void call_with_variant_argsc(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +#ifdef DEBUG_METHODS_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } + + if ((size_t)p_argcount < sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class... P> +void call_with_variant_argsc_dv(T *p_instance, void (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Callable::CallError &r_error, const Vector<Variant> &default_values) { +#ifdef DEBUG_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount; + + int32_t dvs = default_values.size(); +#ifdef DEBUG_ENABLED + if (missing > dvs) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array + for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) { + if (i < p_argcount) { + args[i] = p_args[i]; + } else { + args[i] = &default_values[i - p_argcount + (dvs - missing)]; + } + } + + call_with_variant_argsc_helper(p_instance, p_method, args, r_error, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class R, class... P> +void call_with_variant_args_ret_dv(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error, const Vector<Variant> &default_values) { +#ifdef DEBUG_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount; + + int32_t dvs = default_values.size(); +#ifdef DEBUG_ENABLED + if (missing > dvs) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array + for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) { + if (i < p_argcount) { + args[i] = p_args[i]; + } else { + args[i] = &default_values[i - p_argcount + (dvs - missing)]; + } + } + + call_with_variant_args_ret_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class R, class... P> +void call_with_variant_args_retc_dv(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error, const Vector<Variant> &default_values) { +#ifdef DEBUG_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount; + + int32_t dvs = default_values.size(); +#ifdef DEBUG_ENABLED + if (missing > dvs) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array + for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) { + if (i < p_argcount) { + args[i] = p_args[i]; + } else { + args[i] = &default_values[i - p_argcount + (dvs - missing)]; + } + } + + call_with_variant_args_retc_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class... P> +void call_with_ptr_args(T *p_instance, void (T::*p_method)(P...), const void **p_args) { + call_with_ptr_args_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class... P> +void call_with_ptr_argsc(T *p_instance, void (T::*p_method)(P...) const, const void **p_args) { + call_with_ptr_argsc_helper<T, P...>(p_instance, p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class R, class... P> +void call_with_ptr_args_ret(T *p_instance, R (T::*p_method)(P...), const void **p_args, void *r_ret) { + call_with_ptr_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class R, class... P> +void call_with_ptr_args_retc(T *p_instance, R (T::*p_method)(P...) const, const void **p_args, void *r_ret) { + call_with_ptr_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class R, class... P> +void call_with_ptr_args_static_retc(T *p_instance, R (*p_method)(T *, P...), const void **p_args, void *r_ret) { + call_with_ptr_args_static_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class... P> +void call_with_validated_variant_args(Variant *base, void (T::*p_method)(P...), const Variant **p_args) { + call_with_validated_variant_args_helper<T, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class R, class... P> +void call_with_validated_variant_args_ret(Variant *base, R (T::*p_method)(P...), const Variant **p_args, Variant *r_ret) { + call_with_validated_variant_args_ret_helper<T, R, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class R, class... P> +void call_with_validated_variant_args_retc(Variant *base, R (T::*p_method)(P...) const, const Variant **p_args, Variant *r_ret) { + call_with_validated_variant_args_retc_helper<T, R, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class R, class... P> +void call_with_validated_variant_args_static_retc(Variant *base, R (*p_method)(T *, P...), const Variant **p_args, Variant *r_ret) { + call_with_validated_variant_args_static_retc_helper<T, R, P...>(VariantGetInternalPtr<T>::get_ptr(base), p_method, p_args, r_ret, BuildIndexSequence<sizeof...(P)>{}); +} + +// GCC raises "parameter 'p_args' set but not used" when P = {}, +// it's not clever enough to treat other P values as making this branch valid. +#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-parameter" +#endif + +#ifdef DEBUG_METHODS_ENABLED + +template <class Q> +void call_get_argument_type_helper(int p_arg, int &index, Variant::Type &type) { + if (p_arg == index) { + type = GetTypeInfo<Q>::VARIANT_TYPE; + } + index++; +} + +template <class... P> +Variant::Type call_get_argument_type(int p_arg) { + Variant::Type type = Variant::NIL; + int index = 0; + // I think rocket science is simpler than modern C++. + using expand_type = int[]; + expand_type a{ 0, (call_get_argument_type_helper<P>(p_arg, index, type), 0)... }; + (void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning. + (void)index; // Suppress GCC warning. + return type; +} + +template <class Q> +void call_get_argument_type_info_helper(int p_arg, int &index, PropertyInfo &info) { + if (p_arg == index) { + info = GetTypeInfo<Q>::get_class_info(); + } + index++; +} + +template <class... P> +void call_get_argument_type_info(int p_arg, PropertyInfo &info) { + int index = 0; + // I think rocket science is simpler than modern C++. + using expand_type = int[]; + expand_type a{ 0, (call_get_argument_type_info_helper<P>(p_arg, index, info), 0)... }; + (void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning. + (void)index; // Suppress GCC warning. +} + +template <class Q> +void call_get_argument_metadata_helper(int p_arg, int &index, GodotTypeInfo::Metadata &md) { + if (p_arg == index) { + md = GetTypeInfo<Q>::METADATA; + } + index++; +} + +template <class... P> +GodotTypeInfo::Metadata call_get_argument_metadata(int p_arg) { + GodotTypeInfo::Metadata md = GodotTypeInfo::METADATA_NONE; + + int index = 0; + // I think rocket science is simpler than modern C++. + using expand_type = int[]; + expand_type a{ 0, (call_get_argument_metadata_helper<P>(p_arg, index, md), 0)... }; + (void)a; // Suppress (valid, but unavoidable) -Wunused-variable warning. + (void)index; + return md; +} + +#else + +template <class... P> +Variant::Type call_get_argument_type(int p_arg) { + return Variant::NIL; +} + +#endif // DEBUG_METHODS_ENABLED + +////////////////////// + +template <class T, class R, class... P, size_t... Is> +void call_with_variant_args_ret_helper(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) { + r_error.error = Callable::CallError::CALL_OK; + +#ifdef DEBUG_METHODS_ENABLED + r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); +#else + r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...); +#endif +} + +template <class T, class R, class... P> +void call_with_variant_args_ret(T *p_instance, R (T::*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { +#ifdef DEBUG_METHODS_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } + + if ((size_t)p_argcount < sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + call_with_variant_args_ret_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class R, class... P, size_t... Is> +void call_with_variant_args_retc_helper(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) { + r_error.error = Callable::CallError::CALL_OK; + +#ifdef DEBUG_METHODS_ENABLED + r_ret = (p_instance->*p_method)(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); +#else + r_ret = (p_instance->*p_method)(VariantCaster<P>::cast(*p_args[Is])...); +#endif + (void)p_args; +} + +template <class T, class R, class... P> +void call_with_variant_args_retc(T *p_instance, R (T::*p_method)(P...) const, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { +#ifdef DEBUG_METHODS_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } + + if ((size_t)p_argcount < sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + call_with_variant_args_retc_helper<T, R, P...>(p_instance, p_method, p_args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class T, class R, class... P, size_t... Is> +void call_with_variant_args_retc_static_helper(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, Variant &r_ret, Callable::CallError &r_error, IndexSequence<Is...>) { + r_error.error = Callable::CallError::CALL_OK; + +#ifdef DEBUG_METHODS_ENABLED + r_ret = (p_method)(p_instance, VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); +#else + r_ret = (p_method)(p_instance, VariantCaster<P>::cast(*p_args[Is])...); +#endif + + (void)p_args; +} + +template <class T, class R, class... P> +void call_with_variant_args_retc_static_helper_dv(T *p_instance, R (*p_method)(T *, P...), const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &default_values, Callable::CallError &r_error) { +#ifdef DEBUG_ENABLED + if ((size_t)p_argcount > sizeof...(P)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + int32_t missing = (int32_t)sizeof...(P) - (int32_t)p_argcount; + + int32_t dvs = default_values.size(); +#ifdef DEBUG_ENABLED + if (missing > dvs) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = sizeof...(P); + return; + } +#endif + + const Variant *args[sizeof...(P) == 0 ? 1 : sizeof...(P)]; //avoid zero sized array + for (int32_t i = 0; i < (int32_t)sizeof...(P); i++) { + if (i < p_argcount) { + args[i] = p_args[i]; + } else { + args[i] = &default_values[i - p_argcount + (dvs - missing)]; + } + } + + call_with_variant_args_retc_static_helper(p_instance, p_method, args, r_ret, r_error, BuildIndexSequence<sizeof...(P)>{}); +} + +#if defined(DEBUG_METHODS_ENABLED) && defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + +#endif // BINDER_COMMON_H diff --git a/core/callable.cpp b/core/variant/callable.cpp index c368565687..bd51e2dd1e 100644 --- a/core/callable.cpp +++ b/core/variant/callable.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,10 +31,10 @@ #include "callable.h" #include "callable_bind.h" -#include "core/script_language.h" -#include "message_queue.h" -#include "object.h" -#include "reference.h" +#include "core/object/message_queue.h" +#include "core/object/object.h" +#include "core/object/reference.h" +#include "core/object/script_language.h" void Callable::call_deferred(const Variant **p_arguments, int p_argcount) const { MessageQueue::get_singleton()->push_callable(*this, p_arguments, p_argcount); diff --git a/core/callable.h b/core/variant/callable.h index 936272a681..090fd888e2 100644 --- a/core/callable.h +++ b/core/variant/callable.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +31,9 @@ #ifndef CALLABLE_H #define CALLABLE_H -#include "core/list.h" -#include "core/object_id.h" -#include "core/string_name.h" +#include "core/object/object_id.h" +#include "core/string/string_name.h" +#include "core/templates/list.h" class Object; class Variant; @@ -62,9 +62,9 @@ public: CALL_ERROR_TOO_FEW_ARGUMENTS, // expected is number of arguments CALL_ERROR_INSTANCE_IS_NULL, }; - Error error; - int argument; - int expected; + Error error = Error::CALL_OK; + int argument = 0; + int expected = 0; }; void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const; diff --git a/core/callable_bind.cpp b/core/variant/callable_bind.cpp index da08d3ccbd..10446a5ec1 100644 --- a/core/callable_bind.cpp +++ b/core/variant/callable_bind.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/callable_bind.h b/core/variant/callable_bind.h index 21b9228be3..feb40d1de9 100644 --- a/core/callable_bind.h +++ b/core/variant/callable_bind.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef CALLABLE_BIND_H #define CALLABLE_BIND_H -#include "core/callable.h" -#include "core/variant.h" +#include "core/variant/callable.h" +#include "core/variant/variant.h" class CallableCustomBind : public CallableCustom { Callable callable; diff --git a/core/container_type_validate.h b/core/variant/container_type_validate.h index 8a361aa0ef..f13a37cddd 100644 --- a/core/container_type_validate.h +++ b/core/variant/container_type_validate.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,8 +31,8 @@ #ifndef CONTAINER_TYPE_VALIDATE_H #define CONTAINER_TYPE_VALIDATE_H -#include "core/script_language.h" -#include "core/variant.h" +#include "core/object/script_language.h" +#include "core/variant/variant.h" struct ContainerTypeValidate { Variant::Type type = Variant::NIL; diff --git a/core/dictionary.cpp b/core/variant/dictionary.cpp index 052e1bdae1..b2f7c6aa0a 100644 --- a/core/dictionary.cpp +++ b/core/variant/dictionary.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,9 +30,9 @@ #include "dictionary.h" -#include "core/ordered_hash_map.h" -#include "core/safe_refcount.h" -#include "core/variant.h" +#include "core/templates/ordered_hash_map.h" +#include "core/templates/safe_refcount.h" +#include "core/variant/variant.h" struct DictionaryPrivate { SafeRefCount refcount; @@ -40,7 +40,7 @@ struct DictionaryPrivate { }; void Dictionary::get_key_list(List<Variant> *p_keys) const { - if (_p->variant_map.empty()) { + if (_p->variant_map.is_empty()) { return; } @@ -121,7 +121,7 @@ int Dictionary::size() const { return _p->variant_map.size(); } -bool Dictionary::empty() const { +bool Dictionary::is_empty() const { return !_p->variant_map.size(); } @@ -192,7 +192,7 @@ uint32_t Dictionary::hash() const { Array Dictionary::keys() const { Array varr; - if (_p->variant_map.empty()) { + if (_p->variant_map.is_empty()) { return varr; } @@ -209,7 +209,7 @@ Array Dictionary::keys() const { Array Dictionary::values() const { Array varr; - if (_p->variant_map.empty()) { + if (_p->variant_map.is_empty()) { return varr; } diff --git a/core/dictionary.h b/core/variant/dictionary.h index a01d96ba01..4067ff9fd9 100644 --- a/core/dictionary.h +++ b/core/variant/dictionary.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +31,9 @@ #ifndef DICTIONARY_H #define DICTIONARY_H -#include "core/array.h" -#include "core/list.h" -#include "core/ustring.h" +#include "core/string/ustring.h" +#include "core/templates/list.h" +#include "core/variant/array.h" class Variant; @@ -60,7 +60,7 @@ public: Variant get(const Variant &p_key, const Variant &p_default) const; int size() const; - bool empty() const; + bool is_empty() const; void clear(); bool has(const Variant &p_key) const; diff --git a/core/method_ptrcall.h b/core/variant/method_ptrcall.h index 022ed2a5d6..c294592b63 100644 --- a/core/method_ptrcall.h +++ b/core/variant/method_ptrcall.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,15 +32,12 @@ #define METHOD_PTRCALL_H #include "core/math/transform_2d.h" -#include "core/object_id.h" +#include "core/object/object_id.h" #include "core/typedefs.h" -#include "core/variant.h" - -#ifdef PTRCALL_ENABLED +#include "core/variant/variant.h" template <class T> -struct PtrToArg { -}; +struct PtrToArg {}; #define MAKE_PTRARG(m_type) \ template <> \ @@ -103,6 +100,7 @@ struct PtrToArg { } MAKE_PTRARG(bool); +// Integer types. MAKE_PTRARGCONV(uint8_t, int64_t); MAKE_PTRARGCONV(int8_t, int64_t); MAKE_PTRARGCONV(uint16_t, int64_t); @@ -111,15 +109,16 @@ MAKE_PTRARGCONV(uint32_t, int64_t); MAKE_PTRARGCONV(int32_t, int64_t); MAKE_PTRARG(int64_t); MAKE_PTRARG(uint64_t); +// Float types MAKE_PTRARGCONV(float, double); MAKE_PTRARG(double); MAKE_PTRARG(String); MAKE_PTRARG(Vector2); -MAKE_PTRARG(Rect2); -MAKE_PTRARG_BY_REFERENCE(Vector3); MAKE_PTRARG(Vector2i); +MAKE_PTRARG(Rect2); MAKE_PTRARG(Rect2i); +MAKE_PTRARG_BY_REFERENCE(Vector3); MAKE_PTRARG_BY_REFERENCE(Vector3i); MAKE_PTRARG(Transform2D); MAKE_PTRARG_BY_REFERENCE(Plane); @@ -131,9 +130,10 @@ MAKE_PTRARG_BY_REFERENCE(Color); MAKE_PTRARG(StringName); MAKE_PTRARG(NodePath); MAKE_PTRARG(RID); -MAKE_PTRARG(Dictionary); +// Object doesn't need this. MAKE_PTRARG(Callable); MAKE_PTRARG(Signal); +MAKE_PTRARG(Dictionary); MAKE_PTRARG(Array); MAKE_PTRARG(PackedByteArray); MAKE_PTRARG(PackedInt32Array); @@ -146,7 +146,7 @@ MAKE_PTRARG(PackedVector3Array); MAKE_PTRARG(PackedColorArray); MAKE_PTRARG_BY_REFERENCE(Variant); -//this is for Object +// This is for Object. template <class T> struct PtrToArg<T *> { @@ -170,7 +170,7 @@ struct PtrToArg<const T *> { } }; -//this is for ObjectID +// This is for ObjectID. template <> struct PtrToArg<ObjectID> { @@ -183,7 +183,7 @@ struct PtrToArg<ObjectID> { } }; -//this is for the special cases used by Variant +// This is for the special cases used by Variant. #define MAKE_VECARG(m_type) \ template <> \ @@ -274,18 +274,11 @@ struct PtrToArg<ObjectID> { return ret; \ } \ } -/* -MAKE_VECARG(String); -MAKE_VECARG(uint8_t); -MAKE_VECARG(int); -MAKE_VECARG(float); -MAKE_VECARG(Vector2); -MAKE_VECARG(Vector3); -MAKE_VECARG(Color); -*/ + MAKE_VECARG_ALT(String, StringName); -//for stuff that gets converted to Array vectors +// For stuff that gets converted to Array vectors. + #define MAKE_VECARR(m_type) \ template <> \ struct PtrToArg<Vector<m_type>> { \ @@ -429,6 +422,7 @@ struct PtrToArg<Vector<Face3>> { } } }; + template <> struct PtrToArg<const Vector<Face3> &> { _FORCE_INLINE_ static Vector<Face3> convert(const void *p_ptr) { @@ -450,4 +444,3 @@ struct PtrToArg<const Vector<Face3> &> { }; #endif // METHOD_PTRCALL_H -#endif diff --git a/core/type_info.h b/core/variant/type_info.h index 3c7f59bb84..f61ff29b8f 100644 --- a/core/type_info.h +++ b/core/variant/type_info.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #ifndef TYPE_INFO_H #define TYPE_INFO_H -#ifdef DEBUG_METHODS_ENABLED +#include "core/typedefs.h" template <bool C, typename T = void> struct EnableIf { @@ -153,7 +153,7 @@ MAKE_TYPE_INFO(Transform, Variant::TRANSFORM) MAKE_TYPE_INFO(Color, Variant::COLOR) MAKE_TYPE_INFO(StringName, Variant::STRING_NAME) MAKE_TYPE_INFO(NodePath, Variant::NODE_PATH) -MAKE_TYPE_INFO(RID, Variant::_RID) +MAKE_TYPE_INFO(RID, Variant::RID) MAKE_TYPE_INFO(Callable, Variant::CALLABLE) MAKE_TYPE_INFO(Signal, Variant::SIGNAL) MAKE_TYPE_INFO(Dictionary, Variant::DICTIONARY) @@ -267,11 +267,4 @@ inline StringName __constant_get_enum_name(T param, const String &p_constant) { #define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info()) -#else - -#define MAKE_ENUM_TYPE_INFO(m_enum) -#define CLASS_INFO(m_type) - -#endif // DEBUG_METHODS_ENABLED - #endif // TYPE_INFO_H diff --git a/core/typed_array.h b/core/variant/typed_array.h index 86f26d7550..e0309aa3fe 100644 --- a/core/typed_array.h +++ b/core/variant/typed_array.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +31,9 @@ #ifndef TYPED_ARRAY_H #define TYPED_ARRAY_H -#include "core/array.h" -#include "core/method_ptrcall.h" -#include "core/variant.h" +#include "core/variant/array.h" +#include "core/variant/method_ptrcall.h" +#include "core/variant/variant.h" template <class T> class TypedArray : public Array { @@ -105,7 +105,7 @@ MAKE_TYPED_ARRAY(Transform, Variant::TRANSFORM) MAKE_TYPED_ARRAY(Color, Variant::COLOR) MAKE_TYPED_ARRAY(StringName, Variant::STRING_NAME) MAKE_TYPED_ARRAY(NodePath, Variant::NODE_PATH) -MAKE_TYPED_ARRAY(RID, Variant::_RID) +MAKE_TYPED_ARRAY(RID, Variant::RID) MAKE_TYPED_ARRAY(Callable, Variant::CALLABLE) MAKE_TYPED_ARRAY(Signal, Variant::SIGNAL) MAKE_TYPED_ARRAY(Dictionary, Variant::DICTIONARY) @@ -120,8 +120,6 @@ MAKE_TYPED_ARRAY(Vector<Vector2>, Variant::PACKED_VECTOR2_ARRAY) MAKE_TYPED_ARRAY(Vector<Vector3>, Variant::PACKED_VECTOR3_ARRAY) MAKE_TYPED_ARRAY(Vector<Color>, Variant::PACKED_COLOR_ARRAY) -#ifdef PTRCALL_ENABLED - template <class T> struct PtrToArg<TypedArray<T>> { _FORCE_INLINE_ static TypedArray<T> convert(const void *p_ptr) { @@ -140,8 +138,6 @@ struct PtrToArg<const TypedArray<T> &> { } }; -#endif // PTRCALL_ENABLED - #ifdef DEBUG_METHODS_ENABLED template <class T> @@ -207,7 +203,7 @@ MAKE_TYPED_ARRAY_INFO(Transform, Variant::TRANSFORM) MAKE_TYPED_ARRAY_INFO(Color, Variant::COLOR) MAKE_TYPED_ARRAY_INFO(StringName, Variant::STRING_NAME) MAKE_TYPED_ARRAY_INFO(NodePath, Variant::NODE_PATH) -MAKE_TYPED_ARRAY_INFO(RID, Variant::_RID) +MAKE_TYPED_ARRAY_INFO(RID, Variant::RID) MAKE_TYPED_ARRAY_INFO(Callable, Variant::CALLABLE) MAKE_TYPED_ARRAY_INFO(Signal, Variant::SIGNAL) MAKE_TYPED_ARRAY_INFO(Dictionary, Variant::DICTIONARY) diff --git a/core/variant.cpp b/core/variant/variant.cpp index 181ced0f32..7824776fdb 100644 --- a/core/variant.cpp +++ b/core/variant/variant.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,10 +33,10 @@ #include "core/core_string_names.h" #include "core/debugger/engine_debugger.h" #include "core/io/marshalls.h" +#include "core/io/resource.h" #include "core/math/math_funcs.h" -#include "core/print_string.h" -#include "core/resource.h" -#include "core/variant_parser.h" +#include "core/string/print_string.h" +#include "core/variant/variant_parser.h" #include "scene/gui/control.h" #include "scene/main/node.h" @@ -109,7 +109,7 @@ String Variant::get_type_name(Variant::Type p_type) { return "Color"; } break; - case _RID: { + case RID: { return "RID"; } break; case OBJECT: { @@ -342,7 +342,7 @@ bool Variant::can_convert(Variant::Type p_type_from, Variant::Type p_type_to) { } break; - case _RID: { + case RID: { static const Type valid[] = { OBJECT, NIL @@ -649,7 +649,7 @@ bool Variant::can_convert_strict(Variant::Type p_type_from, Variant::Type p_type } break; - case _RID: { + case RID: { static const Type valid[] = { OBJECT, NIL @@ -891,8 +891,8 @@ bool Variant::is_zero() const { return *reinterpret_cast<const Color *>(_data._mem) == Color(); } break; - case _RID: { - return *reinterpret_cast<const RID *>(_data._mem) == RID(); + case RID: { + return *reinterpret_cast<const ::RID *>(_data._mem) == ::RID(); } break; case OBJECT: { return _get_obj().obj == nullptr; @@ -912,11 +912,11 @@ bool Variant::is_zero() const { } break; case DICTIONARY: { - return reinterpret_cast<const Dictionary *>(_data._mem)->empty(); + return reinterpret_cast<const Dictionary *>(_data._mem)->is_empty(); } break; case ARRAY: { - return reinterpret_cast<const Array *>(_data._mem)->empty(); + return reinterpret_cast<const Array *>(_data._mem)->is_empty(); } break; @@ -1109,8 +1109,8 @@ void Variant::reference(const Variant &p_variant) { memnew_placement(_data._mem, Color(*reinterpret_cast<const Color *>(p_variant._data._mem))); } break; - case _RID: { - memnew_placement(_data._mem, RID(*reinterpret_cast<const RID *>(p_variant._data._mem))); + case RID: { + memnew_placement(_data._mem, ::RID(*reinterpret_cast<const ::RID *>(p_variant._data._mem))); } break; case OBJECT: { memnew_placement(_data._mem, ObjData); @@ -1266,7 +1266,7 @@ void Variant::zero() { } } -void Variant::clear() { +void Variant::_clear_internal() { switch (type) { case STRING: { reinterpret_cast<String *>(_data._mem)->~String(); @@ -1311,9 +1311,11 @@ void Variant::clear() { _get_obj().obj = nullptr; _get_obj().id = ObjectID(); } break; - case _RID: { + case RID: { // not much need probably - reinterpret_cast<RID *>(_data._mem)->~RID(); + // Can't seem to use destructor + scoping operator, so hack. + typedef ::RID RID_Class; + reinterpret_cast<RID_Class *>(_data._mem)->~RID_Class(); } break; case CALLABLE: { reinterpret_cast<Callable *>(_data._mem)->~Callable(); @@ -1358,8 +1360,6 @@ void Variant::clear() { default: { } /* not needed */ } - - type = NIL; } Variant::operator signed int() const { @@ -1849,8 +1849,8 @@ String Variant::stringify(List<const void *> &stack) const { const Signal &s = *reinterpret_cast<const Signal *>(_data._mem); return s; } break; - case _RID: { - const RID &s = *reinterpret_cast<const RID *>(_data._mem); + case RID: { + const ::RID &s = *reinterpret_cast<const ::RID *>(_data._mem); return "RID(" + itos(s.get_id()) + ")"; } break; default: { @@ -2041,25 +2041,25 @@ Variant::operator NodePath() const { } } -Variant::operator RID() const { - if (type == _RID) { - return *reinterpret_cast<const RID *>(_data._mem); +Variant::operator ::RID() const { + if (type == RID) { + return *reinterpret_cast<const ::RID *>(_data._mem); } else if (type == OBJECT && _get_obj().obj == nullptr) { - return RID(); + return ::RID(); } else if (type == OBJECT && _get_obj().obj) { #ifdef DEBUG_ENABLED if (EngineDebugger::is_active()) { - ERR_FAIL_COND_V_MSG(ObjectDB::get_instance(_get_obj().id) == nullptr, RID(), "Invalid pointer (object was freed)."); + ERR_FAIL_COND_V_MSG(ObjectDB::get_instance(_get_obj().id) == nullptr, ::RID(), "Invalid pointer (object was freed)."); } #endif Callable::CallError ce; Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->get_rid, nullptr, 0, ce); - if (ce.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::_RID) { + if (ce.error == Callable::CallError::CALL_OK && ret.get_type() == Variant::RID) { return ret; } - return RID(); + return ::RID(); } else { - return RID(); + return ::RID(); } } @@ -2263,9 +2263,9 @@ Variant::operator Vector<Color>() const { /* helpers */ -Variant::operator Vector<RID>() const { +Variant::operator Vector<::RID>() const { Array va = operator Array(); - Vector<RID> rids; + Vector<::RID> rids; rids.resize(va.size()); for (int i = 0; i < rids.size(); i++) { rids.write[i] = va[i]; @@ -2338,8 +2338,8 @@ Variant::operator Vector<StringName>() const { return to; } -Variant::operator Margin() const { - return (Margin) operator int(); +Variant::operator Side() const { + return (Side) operator int(); } Variant::operator Orientation() const { @@ -2520,9 +2520,9 @@ Variant::Variant(const NodePath &p_node_path) { memnew_placement(_data._mem, NodePath(p_node_path)); } -Variant::Variant(const RID &p_rid) { - type = _RID; - memnew_placement(_data._mem, RID(p_rid)); +Variant::Variant(const ::RID &p_rid) { + type = RID; + memnew_placement(_data._mem, ::RID(p_rid)); } Variant::Variant(const Object *p_object) { @@ -2580,7 +2580,7 @@ Variant::Variant(const Vector<Plane> &p_array) { } } -Variant::Variant(const Vector<RID> &p_array) { +Variant::Variant(const Vector<::RID> &p_array) { type = ARRAY; Array *rid_array = memnew_placement(_data._mem, Array); @@ -2753,8 +2753,8 @@ void Variant::operator=(const Variant &p_variant) { case COLOR: { *reinterpret_cast<Color *>(_data._mem) = *reinterpret_cast<const Color *>(p_variant._data._mem); } break; - case _RID: { - *reinterpret_cast<RID *>(_data._mem) = *reinterpret_cast<const RID *>(p_variant._data._mem); + case RID: { + *reinterpret_cast<::RID *>(_data._mem) = *reinterpret_cast<const ::RID *>(p_variant._data._mem); } break; case OBJECT: { if (_get_obj().id.is_reference()) { @@ -2955,8 +2955,8 @@ uint32_t Variant::hash() const { return hash_djb2_one_float(reinterpret_cast<const Color *>(_data._mem)->a, hash); } break; - case _RID: { - return hash_djb2_one_64(reinterpret_cast<const RID *>(_data._mem)->get_id()); + case RID: { + return hash_djb2_one_64(reinterpret_cast<const ::RID *>(_data._mem)->get_id()); } break; case OBJECT: { return hash_djb2_one_64(make_uint64_t(_get_obj().obj)); @@ -3401,7 +3401,8 @@ Variant Variant::call(const StringName &p_method, VARIANT_ARG_DECLARE) { Callable::CallError error; - Variant ret = call(p_method, argptr, argc, error); + Variant ret; + call(p_method, argptr, argc, ret, error); switch (error.error) { case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: { @@ -3435,6 +3436,30 @@ String Variant::get_construct_string() const { return vars; } +String Variant::get_call_error_text(const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) { + String err_text; + + if (ce.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) { + int errorarg = ce.argument; + if (p_argptrs) { + err_text = "Cannot convert argument " + itos(errorarg + 1) + " from " + Variant::get_type_name(p_argptrs[errorarg]->get_type()) + " to " + Variant::get_type_name(Variant::Type(ce.expected)) + "."; + } else { + err_text = "Cannot convert argument " + itos(errorarg + 1) + " from [missing argptr, type unknown] to " + Variant::get_type_name(Variant::Type(ce.expected)) + "."; + } + } else if (ce.error == Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS) { + err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + "."; + } else if (ce.error == Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS) { + err_text = "Method expected " + itos(ce.argument) + " arguments, but called with " + itos(p_argcount) + "."; + } else if (ce.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) { + err_text = "Method not found."; + } else if (ce.error == Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL) { + err_text = "Instance is null"; + } else if (ce.error == Callable::CallError::CALL_OK) { + return "Call OK"; + } + return "'" + String(p_method) + "': " + err_text; +} + String Variant::get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce) { String err_text; @@ -3519,3 +3544,18 @@ String vformat(const String &p_text, const Variant &p1, const Variant &p2, const return fmt; } + +void Variant::register_types() { + _register_variant_operators(); + _register_variant_methods(); + _register_variant_setters_getters(); + _register_variant_constructors(); + _register_variant_utility_functions(); +} +void Variant::unregister_types() { + _unregister_variant_operators(); + _unregister_variant_methods(); + _unregister_variant_setters_getters(); + _unregister_variant_constructors(); + _unregister_variant_utility_functions(); +} diff --git a/core/variant.h b/core/variant/variant.h index 112003a7ae..5050aa24ec 100644 --- a/core/variant.h +++ b/core/variant/variant.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,13 +31,10 @@ #ifndef VARIANT_H #define VARIANT_H -#include "core/array.h" -#include "core/callable.h" -#include "core/color.h" -#include "core/dictionary.h" #include "core/io/ip_address.h" #include "core/math/aabb.h" #include "core/math/basis.h" +#include "core/math/color.h" #include "core/math/face3.h" #include "core/math/plane.h" #include "core/math/quat.h" @@ -45,10 +42,13 @@ #include "core/math/transform_2d.h" #include "core/math/vector3.h" #include "core/math/vector3i.h" -#include "core/node_path.h" -#include "core/object_id.h" -#include "core/rid.h" -#include "core/ustring.h" +#include "core/object/object_id.h" +#include "core/string/node_path.h" +#include "core/string/ustring.h" +#include "core/templates/rid.h" +#include "core/variant/array.h" +#include "core/variant/callable.h" +#include "core/variant/dictionary.h" class Object; class Node; // helper @@ -97,7 +97,7 @@ public: COLOR, STRING_NAME, NODE_PATH, - _RID, + RID, OBJECT, CALLABLE, SIGNAL, @@ -128,7 +128,7 @@ private: struct ObjData { ObjectID id; - Object *obj; + Object *obj = nullptr; }; /* array helpers */ @@ -207,7 +207,68 @@ private: } _data alignas(8); void reference(const Variant &p_variant); - void clear(); + + void _clear_internal(); + + _FORCE_INLINE_ void clear() { + static const bool needs_deinit[Variant::VARIANT_MAX] = { + false, //NIL, + false, //BOOL, + false, //INT, + false, //FLOAT, + true, //STRING, + false, //VECTOR2, + false, //VECTOR2I, + false, //RECT2, + false, //RECT2I, + false, //VECTOR3, + false, //VECTOR3I, + true, //TRANSFORM2D, + false, //PLANE, + false, //QUAT, + true, //AABB, + true, //BASIS, + true, //TRANSFORM, + + // misc types + false, //COLOR, + true, //STRING_NAME, + true, //NODE_PATH, + false, //RID, + true, //OBJECT, + true, //CALLABLE, + true, //SIGNAL, + true, //DICTIONARY, + true, //ARRAY, + + // typed arrays + true, //PACKED_BYTE_ARRAY, + true, //PACKED_INT32_ARRAY, + true, //PACKED_INT64_ARRAY, + true, //PACKED_FLOAT32_ARRAY, + true, //PACKED_FLOAT64_ARRAY, + true, //PACKED_STRING_ARRAY, + true, //PACKED_VECTOR2_ARRAY, + true, //PACKED_VECTOR3_ARRAY, + true, //PACKED_COLOR_ARRAY, + }; + + if (unlikely(needs_deinit[type])) { //make it fast for types that dont need deinit + _clear_internal(); + } + type = NIL; + } + + static void _register_variant_operators(); + static void _unregister_variant_operators(); + static void _register_variant_methods(); + static void _unregister_variant_methods(); + static void _register_variant_setters_getters(); + static void _unregister_variant_setters_getters(); + static void _register_variant_constructors(); + static void _unregister_variant_constructors(); + static void _register_variant_utility_functions(); + static void _unregister_variant_utility_functions(); public: _FORCE_INLINE_ Type get_type() const { @@ -266,7 +327,7 @@ public: operator Color() const; operator NodePath() const; - operator RID() const; + operator ::RID() const; operator Object *() const; operator Node *() const; @@ -291,11 +352,11 @@ public: operator Vector<Variant>() const; operator Vector<StringName>() const; - operator Vector<RID>() const; + operator Vector<::RID>() const; operator Vector<Vector2>() const; // some core type enums to convert to - operator Margin() const; + operator Side() const; operator Orientation() const; operator IP_Address() const; @@ -309,7 +370,6 @@ public: #ifdef NEED_LONG_INT Variant(signed long p_long); // real one Variant(unsigned long p_long); -//Variant(long unsigned int p_long); #endif Variant(signed short p_short); // real one Variant(unsigned short p_short); @@ -338,7 +398,7 @@ public: Variant(const Transform &p_transform); Variant(const Color &p_color); Variant(const NodePath &p_node_path); - Variant(const RID &p_rid); + Variant(const ::RID &p_rid); Variant(const Object *p_object); Variant(const Callable &p_callable); Variant(const Signal &p_signal); @@ -358,14 +418,13 @@ public: Variant(const Vector<Variant> &p_array); Variant(const Vector<StringName> &p_array); - Variant(const Vector<RID> &p_array); // helper + Variant(const Vector<::RID> &p_array); // helper Variant(const Vector<Vector2> &p_array); // helper Variant(const IP_Address &p_address); // If this changes the table in variant_op must be updated enum Operator { - //comparison OP_EQUAL, OP_NOT_EQUAL, @@ -381,7 +440,6 @@ public: OP_NEGATE, OP_POSITIVE, OP_MODULE, - OP_STRING_CONCAT, //bitwise OP_SHIFT_LEFT, OP_SHIFT_RIGHT, @@ -409,30 +467,133 @@ public: return res; } + static Variant::Type get_operator_return_type(Operator p_operator, Type p_type_a, Type p_type_b); + typedef void (*ValidatedOperatorEvaluator)(const Variant *left, const Variant *right, Variant *r_ret); + static ValidatedOperatorEvaluator get_validated_operator_evaluator(Operator p_operator, Type p_type_a, Type p_type_b); + typedef void (*PTROperatorEvaluator)(const void *left, const void *right, void *r_ret); + static PTROperatorEvaluator get_ptr_operator_evaluator(Operator p_operator, Type p_type_a, Type p_type_b); + void zero(); Variant duplicate(bool deep = false) const; static void blend(const Variant &a, const Variant &b, float c, Variant &r_dst); static void interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst); - void call_ptr(const StringName &p_method, const Variant **p_args, int p_argcount, Variant *r_ret, Callable::CallError &r_error); - Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error); + /* Built-In Methods */ + + typedef void (*ValidatedBuiltInMethod)(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret); + typedef void (*PTRBuiltInMethod)(void *p_base, const void **p_args, void *r_ret, int p_argcount); + + static bool has_builtin_method(Variant::Type p_type, const StringName &p_method); + + 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 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); + static Vector<Variant> get_builtin_method_default_arguments(Variant::Type p_type, const StringName &p_method); + static bool has_builtin_method_return_value(Variant::Type p_type, const StringName &p_method); + static Variant::Type get_builtin_method_return_type(Variant::Type p_type, const StringName &p_method); + static bool is_builtin_method_const(Variant::Type p_type, const StringName &p_method); + static bool is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method); + static void get_builtin_method_list(Variant::Type p_type, List<StringName> *p_list); + static int get_builtin_method_count(Variant::Type p_type); + + void call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error); Variant call(const StringName &p_method, const Variant &p_arg1 = Variant(), const Variant &p_arg2 = Variant(), const Variant &p_arg3 = Variant(), const Variant &p_arg4 = Variant(), const Variant &p_arg5 = Variant()); + static String get_call_error_text(const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce); static String get_call_error_text(Object *p_base, const StringName &p_method, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce); static String get_callable_error_text(const Callable &p_callable, const Variant **p_argptrs, int p_argcount, const Callable::CallError &ce); - static Variant construct(const Variant::Type, const Variant **p_args, int p_argcount, Callable::CallError &r_error, bool p_strict = true); - + //dynamic (includes Object) void get_method_list(List<MethodInfo> *p_list) const; bool has_method(const StringName &p_method) const; - static Vector<Variant::Type> get_method_argument_types(Variant::Type p_type, const StringName &p_method); - static Vector<Variant> get_method_default_arguments(Variant::Type p_type, const StringName &p_method); - static Variant::Type get_method_return_type(Variant::Type p_type, const StringName &p_method, bool *r_has_return = nullptr); - static Vector<StringName> get_method_argument_names(Variant::Type p_type, const StringName &p_method); - static bool is_method_const(Variant::Type p_type, const StringName &p_method); - void set_named(const StringName &p_index, const Variant &p_value, bool *r_valid = nullptr); - Variant get_named(const StringName &p_index, bool *r_valid = nullptr) const; + /* Constructors */ + + typedef void (*ValidatedConstructor)(Variant *r_base, const Variant **p_args); + typedef void (*PTRConstructor)(void *base, const void **p_args); + + static int get_constructor_count(Variant::Type p_type); + static ValidatedConstructor get_validated_constructor(Variant::Type p_type, int p_constructor); + static PTRConstructor get_ptr_constructor(Variant::Type p_type, int p_constructor); + static int get_constructor_argument_count(Variant::Type p_type, int p_constructor); + static Variant::Type get_constructor_argument_type(Variant::Type p_type, int p_constructor, int p_argument); + static String get_constructor_argument_name(Variant::Type p_type, int p_constructor, int p_argument); + static void construct(Variant::Type, Variant &base, const Variant **p_args, int p_argcount, Callable::CallError &r_error); + + static void get_constructor_list(Type p_type, List<MethodInfo> *r_list); //convenience + + /* Properties */ + + void set_named(const StringName &p_member, const Variant &p_value, bool &r_valid); + Variant get_named(const StringName &p_member, bool &r_valid) const; + + typedef void (*ValidatedSetter)(Variant *base, const Variant *value); + typedef void (*ValidatedGetter)(const Variant *base, Variant *value); + + static bool has_member(Variant::Type p_type, const StringName &p_member); + static Variant::Type get_member_type(Variant::Type p_type, const StringName &p_member); + static void get_member_list(Type p_type, List<StringName> *r_members); + static int get_member_count(Type p_type); + + static ValidatedSetter get_member_validated_setter(Variant::Type p_type, const StringName &p_member); + static ValidatedGetter get_member_validated_getter(Variant::Type p_type, const StringName &p_member); + + typedef void (*PTRSetter)(void *base, const void *value); + typedef void (*PTRGetter)(const void *base, void *value); + + static PTRSetter get_member_ptr_setter(Variant::Type p_type, const StringName &p_member); + static PTRGetter get_member_ptr_getter(Variant::Type p_type, const StringName &p_member); + + /* Indexing */ + + static bool has_indexing(Variant::Type p_type); + static Variant::Type get_indexed_element_type(Variant::Type p_type); + + typedef void (*ValidatedIndexedSetter)(Variant *base, int64_t index, const Variant *value, bool *oob); + typedef void (*ValidatedIndexedGetter)(const Variant *base, int64_t index, Variant *value, bool *oob); + + static ValidatedIndexedSetter get_member_validated_indexed_setter(Variant::Type p_type); + static ValidatedIndexedGetter get_member_validated_indexed_getter(Variant::Type p_type); + + typedef void (*PTRIndexedSetter)(void *base, int64_t index, const void *value); + typedef void (*PTRIndexedGetter)(const void *base, int64_t index, void *value); + + static PTRIndexedSetter get_member_ptr_indexed_setter(Variant::Type p_type); + static PTRIndexedGetter get_member_ptr_indexed_getter(Variant::Type p_type); + + void set_indexed(int64_t p_index, const Variant &p_value, bool &r_valid, bool &r_oob); + Variant get_indexed(int64_t p_index, bool &r_valid, bool &r_oob) const; + + uint64_t get_indexed_size() const; + + /* Keying */ + + static bool is_keyed(Variant::Type p_type); + + typedef void (*ValidatedKeyedSetter)(Variant *base, const Variant *key, const Variant *value, bool *valid); + typedef void (*ValidatedKeyedGetter)(const Variant *base, const Variant *key, Variant *value, bool *valid); + typedef bool (*ValidatedKeyedChecker)(const Variant *base, const Variant *key, bool *valid); + + static ValidatedKeyedSetter get_member_validated_keyed_setter(Variant::Type p_type); + static ValidatedKeyedGetter get_member_validated_keyed_getter(Variant::Type p_type); + static ValidatedKeyedChecker get_member_validated_keyed_checker(Variant::Type p_type); + + typedef void (*PTRKeyedSetter)(void *base, const void *key, const void *value); + typedef void (*PTRKeyedGetter)(const void *base, const void *key, void *value); + typedef bool (*PTRKeyedChecker)(const void *base, const void *key); + + static PTRKeyedSetter get_member_ptr_keyed_setter(Variant::Type p_type); + static PTRKeyedGetter get_member_ptr_keyed_getter(Variant::Type p_type); + static PTRKeyedChecker get_member_ptr_keyed_checker(Variant::Type p_type); + + void set_keyed(const Variant &p_key, const Variant &p_value, bool &r_valid); + Variant get_keyed(const Variant &p_key, bool &r_valid) const; + 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; @@ -444,6 +605,33 @@ public: void get_property_list(List<PropertyInfo> *p_list) const; + static void call_utility_function(const StringName &p_name, Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error); + static bool has_utility_function(const StringName &p_name); + + typedef void (*ValidatedUtilityFunction)(Variant *r_ret, const Variant **p_args, int p_argcount); + typedef void (*PTRUtilityFunction)(void *r_ret, const void **p_args, int p_argcount); + + static ValidatedUtilityFunction get_validated_utility_function(const StringName &p_name); + static PTRUtilityFunction get_ptr_utility_function(const StringName &p_name); + + enum UtilityFunctionType { + UTILITY_FUNC_TYPE_MATH, + UTILITY_FUNC_TYPE_RANDOM, + UTILITY_FUNC_TYPE_GENERAL, + }; + + static UtilityFunctionType get_utility_function_type(const StringName &p_name); + + static int get_utility_function_argument_count(const StringName &p_name); + static Variant::Type get_utility_function_argument_type(const StringName &p_name, int p_arg); + static String get_utility_function_argument_name(const StringName &p_name, int p_arg); + static bool has_utility_function_return_value(const StringName &p_name); + static Variant::Type get_utility_function_return_type(const StringName &p_name); + static bool is_utility_function_vararg(const StringName &p_name); + + static void get_utility_function_list(List<StringName> *r_functions); + static int get_utility_function_count(); + //argsVariant call() bool operator==(const Variant &p_variant) const; @@ -456,8 +644,8 @@ public: String stringify(List<const void *> &stack) const; void static_assign(const Variant &p_variant); - static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list); static void get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants); + static int get_constants_count_for_type(Variant::Type p_type); static bool has_constant(Variant::Type p_type, const StringName &p_value); static Variant get_constant_value(Variant::Type p_type, const StringName &p_value, bool *r_valid = nullptr); @@ -469,12 +657,13 @@ public: void operator=(const Variant &p_variant); // only this is enough for all the other types + static void register_types(); + static void unregister_types(); + Variant(const Variant &p_variant); _FORCE_INLINE_ Variant() {} _FORCE_INLINE_ ~Variant() { - if (type != Variant::NIL) { - clear(); - } + clear(); } }; diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp new file mode 100644 index 0000000000..85e3b29279 --- /dev/null +++ b/core/variant/variant_call.cpp @@ -0,0 +1,1579 @@ +/*************************************************************************/ +/* variant_call.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "variant.h" + +#include "core/core_string_names.h" +#include "core/crypto/crypto_core.h" +#include "core/debugger/engine_debugger.h" +#include "core/io/compression.h" +#include "core/object/class_db.h" +#include "core/os/os.h" +#include "core/templates/local_vector.h" +#include "core/templates/oa_hash_map.h" + +typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args); +typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args); + +template <class R, class T, class... P> +static _FORCE_INLINE_ void vc_method_call(R (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { + call_with_variant_args_ret_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_ret, r_error, p_defvals); +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ void vc_method_call(R (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { + call_with_variant_args_retc_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_ret, r_error, p_defvals); +} + +template <class T, class... P> +static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...), Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { + call_with_variant_args_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals); +} + +template <class T, class... P> +static _FORCE_INLINE_ void vc_method_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { + call_with_variant_argsc_dv(VariantGetInternalPtr<T>::get_ptr(base), method, p_args, p_argcount, r_error, p_defvals); +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ void vc_validated_call(R (T::*method)(P...), Variant *base, const Variant **p_args, Variant *r_ret) { + call_with_validated_variant_args_ret(base, method, p_args, r_ret); +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ void vc_validated_call(R (T::*method)(P...) const, Variant *base, const Variant **p_args, Variant *r_ret) { + call_with_validated_variant_args_retc(base, method, p_args, r_ret); +} +template <class T, class... P> +static _FORCE_INLINE_ void vc_validated_call(void (T::*method)(P...), Variant *base, const Variant **p_args, Variant *r_ret) { + call_with_validated_variant_args(base, method, p_args); +} + +template <class T, class... P> +static _FORCE_INLINE_ void vc_validated_call(void (T::*method)(P...) const, Variant *base, const Variant **p_args, Variant *r_ret) { + call_with_validated_variant_argsc(base, method, p_args); +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ void vc_ptrcall(R (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) { + call_with_ptr_args_ret(reinterpret_cast<T *>(p_base), method, p_args, r_ret); +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ void vc_ptrcall(R (T::*method)(P...) const, void *p_base, const void **p_args, void *r_ret) { + call_with_ptr_args_retc(reinterpret_cast<T *>(p_base), method, p_args, r_ret); +} + +template <class T, class... P> +static _FORCE_INLINE_ void vc_ptrcall(void (T::*method)(P...), void *p_base, const void **p_args, void *r_ret) { + call_with_ptr_args(reinterpret_cast<T *>(p_base), method, p_args); +} + +template <class T, class... P> +static _FORCE_INLINE_ void vc_ptrcall(void (T::*method)(P...) const, void *p_base, const void **p_args, void *r_ret) { + call_with_ptr_argsc(reinterpret_cast<T *>(p_base), method, p_args); +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ void vc_change_return_type(R (T::*method)(P...), Variant *v) { + VariantTypeAdjust<R>::adjust(v); +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ void vc_change_return_type(R (T::*method)(P...) const, Variant *v) { + VariantTypeAdjust<R>::adjust(v); +} + +template <class T, class... P> +static _FORCE_INLINE_ void vc_change_return_type(void (T::*method)(P...), Variant *v) { + VariantInternal::clear(v); +} + +template <class T, class... P> +static _FORCE_INLINE_ void vc_change_return_type(void (T::*method)(P...) const, Variant *v) { + VariantInternal::clear(v); +} + +template <class R, class... P> +static _FORCE_INLINE_ void vc_change_return_type(R (*method)(P...), Variant *v) { + VariantTypeAdjust<R>::adjust(v); +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ int vc_get_argument_count(R (T::*method)(P...)) { + return sizeof...(P); +} +template <class R, class T, class... P> +static _FORCE_INLINE_ int vc_get_argument_count(R (T::*method)(P...) const) { + return sizeof...(P); +} + +template <class T, class... P> +static _FORCE_INLINE_ int vc_get_argument_count(void (T::*method)(P...)) { + return sizeof...(P); +} + +template <class T, class... P> +static _FORCE_INLINE_ int vc_get_argument_count(void (T::*method)(P...) const) { + return sizeof...(P); +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ int vc_get_argument_count(R (*method)(T *, P...)) { + return sizeof...(P); +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_argument_type(R (T::*method)(P...), int p_arg) { + return call_get_argument_type<P...>(p_arg); +} +template <class R, class T, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_argument_type(R (T::*method)(P...) const, int p_arg) { + return call_get_argument_type<P...>(p_arg); +} + +template <class T, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_argument_type(void (T::*method)(P...), int p_arg) { + return call_get_argument_type<P...>(p_arg); +} + +template <class T, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_argument_type(void (T::*method)(P...) const, int p_arg) { + return call_get_argument_type<P...>(p_arg); +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_argument_type(R (*method)(T *, P...), int p_arg) { + return call_get_argument_type<P...>(p_arg); +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_return_type(R (T::*method)(P...)) { + return GetTypeInfo<R>::VARIANT_TYPE; +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_return_type(R (T::*method)(P...) const) { + return GetTypeInfo<R>::VARIANT_TYPE; +} + +template <class T, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_return_type(void (T::*method)(P...)) { + return Variant::NIL; +} + +template <class T, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_return_type(void (T::*method)(P...) const) { + return Variant::NIL; +} + +template <class R, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_return_type(R (*method)(P...)) { + return GetTypeInfo<R>::VARIANT_TYPE; +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ bool vc_has_return_type(R (T::*method)(P...)) { + return true; +} +template <class R, class T, class... P> +static _FORCE_INLINE_ bool vc_has_return_type(R (T::*method)(P...) const) { + return true; +} + +template <class T, class... P> +static _FORCE_INLINE_ bool vc_has_return_type(void (T::*method)(P...)) { + return false; +} + +template <class T, class... P> +static _FORCE_INLINE_ bool vc_has_return_type(void (T::*method)(P...) const) { + return false; +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ bool vc_is_const(R (T::*method)(P...)) { + return false; +} +template <class R, class T, class... P> +static _FORCE_INLINE_ bool vc_is_const(R (T::*method)(P...) const) { + return true; +} + +template <class T, class... P> +static _FORCE_INLINE_ bool vc_is_const(void (T::*method)(P...)) { + return false; +} + +template <class T, class... P> +static _FORCE_INLINE_ bool vc_is_const(void (T::*method)(P...) const) { + return true; +} + +template <class R, class T, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_base_type(R (T::*method)(P...)) { + return GetTypeInfo<T>::VARIANT_TYPE; +} +template <class R, class T, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_base_type(R (T::*method)(P...) const) { + return GetTypeInfo<T>::VARIANT_TYPE; +} + +template <class T, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...)) { + return GetTypeInfo<T>::VARIANT_TYPE; +} + +template <class T, class... P> +static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...) const) { + return GetTypeInfo<T>::VARIANT_TYPE; +} + +#define METHOD_CLASS(m_class, m_method_name, m_method_ptr) \ + struct Method_##m_class##_##m_method_name { \ + static void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \ + vc_method_call(m_method_ptr, base, p_args, p_argcount, r_ret, p_defvals, r_error); \ + } \ + static void validated_call(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret) { \ + vc_change_return_type(m_method_ptr, r_ret); \ + vc_validated_call(m_method_ptr, base, p_args, r_ret); \ + } \ + static void ptrcall(void *p_base, const void **p_args, void *r_ret, int p_argcount) { \ + vc_ptrcall(m_method_ptr, p_base, p_args, r_ret); \ + } \ + static int get_argument_count() { \ + return vc_get_argument_count(m_method_ptr); \ + } \ + static Variant::Type get_argument_type(int p_arg) { \ + return vc_get_argument_type(m_method_ptr, p_arg); \ + } \ + static Variant::Type get_return_type() { \ + return vc_get_return_type(m_method_ptr); \ + } \ + static bool has_return_type() { \ + return vc_has_return_type(m_method_ptr); \ + } \ + static bool is_const() { \ + return vc_is_const(m_method_ptr); \ + } \ + static bool is_vararg() { \ + return false; \ + } \ + static Variant::Type get_base_type() { \ + return vc_get_base_type(m_method_ptr); \ + } \ + static StringName get_name() { \ + return #m_method_name; \ + } \ + }; + +template <class R, class T, class... P> +static _FORCE_INLINE_ void vc_ptrcall(R (*method)(T *, P...), void *p_base, const void **p_args, void *r_ret) { + call_with_ptr_args_static_retc<T, R, P...>(reinterpret_cast<T *>(p_base), method, p_args, r_ret); +} + +#define FUNCTION_CLASS(m_class, m_method_name, m_method_ptr) \ + struct Method_##m_class##_##m_method_name { \ + static void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \ + call_with_variant_args_retc_static_helper_dv(VariantGetInternalPtr<m_class>::get_ptr(base), m_method_ptr, p_args, p_argcount, r_ret, p_defvals, r_error); \ + } \ + static void validated_call(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret) { \ + vc_change_return_type(m_method_ptr, r_ret); \ + call_with_validated_variant_args_static_retc(base, m_method_ptr, p_args, r_ret); \ + } \ + static void ptrcall(void *p_base, const void **p_args, void *r_ret, int p_argcount) { \ + vc_ptrcall(m_method_ptr, p_base, p_args, r_ret); \ + } \ + static int get_argument_count() { \ + return vc_get_argument_count(m_method_ptr); \ + } \ + static Variant::Type get_argument_type(int p_arg) { \ + return vc_get_argument_type(m_method_ptr, p_arg); \ + } \ + static Variant::Type get_return_type() { \ + return vc_get_return_type(m_method_ptr); \ + } \ + static bool has_return_type() { \ + return true; \ + } \ + static bool is_const() { \ + return true; \ + } \ + static bool is_vararg() { \ + return false; \ + } \ + static Variant::Type get_base_type() { \ + return GetTypeInfo<m_class>::VARIANT_TYPE; \ + } \ + static StringName get_name() { \ + return #m_method_name; \ + } \ + }; + +#define VARARG_CLASS(m_class, m_method_name, m_method_ptr, m_has_return, m_return_type) \ + struct Method_##m_class##_##m_method_name { \ + static void call(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error) { \ + m_method_ptr(base, p_args, p_argcount, r_ret, r_error); \ + } \ + static void validated_call(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret) { \ + Callable::CallError ce; \ + m_method_ptr(base, p_args, p_argcount, *r_ret, ce); \ + } \ + static void ptrcall(void *p_base, const void **p_args, void *r_ret, int p_argcount) { \ + LocalVector<Variant> vars; \ + vars.resize(p_argcount); \ + LocalVector<const Variant *> vars_ptrs; \ + vars_ptrs.resize(p_argcount); \ + for (int i = 0; i < p_argcount; i++) { \ + vars[i] = PtrToArg<Variant>::convert(p_args[i]); \ + vars_ptrs[i] = &vars[i]; \ + } \ + Variant base = PtrToArg<m_class>::convert(p_base); \ + Variant ret; \ + Callable::CallError ce; \ + m_method_ptr(&base, (const Variant **)&vars_ptrs[0], p_argcount, ret, ce); \ + if (m_has_return) { \ + m_return_type r = ret; \ + PtrToArg<m_return_type>::encode(ret, r_ret); \ + } \ + } \ + static int get_argument_count() { \ + return 0; \ + } \ + static Variant::Type get_argument_type(int p_arg) { \ + return Variant::NIL; \ + } \ + static Variant::Type get_return_type() { \ + return GetTypeInfo<m_return_type>::VARIANT_TYPE; \ + } \ + static bool has_return_type() { \ + return m_has_return; \ + } \ + static bool is_const() { \ + return true; \ + } \ + static bool is_vararg() { \ + return true; \ + } \ + static Variant::Type get_base_type() { \ + return GetTypeInfo<m_class>::VARIANT_TYPE; \ + } \ + static StringName get_name() { \ + return #m_method_name; \ + } \ + }; + +struct _VariantCall { + static String func_PackedByteArray_get_string_from_ascii(PackedByteArray *p_instance) { + String s; + if (p_instance->size() > 0) { + const uint8_t *r = p_instance->ptr(); + CharString cs; + cs.resize(p_instance->size() + 1); + copymem(cs.ptrw(), r, p_instance->size()); + cs[p_instance->size()] = 0; + + s = cs.get_data(); + } + return s; + } + + static String func_PackedByteArray_get_string_from_utf8(PackedByteArray *p_instance) { + String s; + if (p_instance->size() > 0) { + const uint8_t *r = p_instance->ptr(); + s.parse_utf8((const char *)r, p_instance->size()); + } + return s; + } + + static String func_PackedByteArray_get_string_from_utf16(PackedByteArray *p_instance) { + String s; + if (p_instance->size() > 0) { + const uint8_t *r = p_instance->ptr(); + s.parse_utf16((const char16_t *)r, floor((double)p_instance->size() / (double)sizeof(char16_t))); + } + return s; + } + + static String func_PackedByteArray_get_string_from_utf32(PackedByteArray *p_instance) { + String s; + if (p_instance->size() > 0) { + const uint8_t *r = p_instance->ptr(); + s = String((const char32_t *)r, floor((double)p_instance->size() / (double)sizeof(char32_t))); + } + return s; + } + + static PackedByteArray func_PackedByteArray_compress(PackedByteArray *p_instance, int p_mode) { + PackedByteArray compressed; + + if (p_instance->size() > 0) { + Compression::Mode mode = (Compression::Mode)(p_mode); + compressed.resize(Compression::get_max_compressed_buffer_size(p_instance->size(), mode)); + int result = Compression::compress(compressed.ptrw(), p_instance->ptr(), p_instance->size(), mode); + + result = result >= 0 ? result : 0; + compressed.resize(result); + } + + return compressed; + } + + static PackedByteArray func_PackedByteArray_decompress(PackedByteArray *p_instance, int64_t p_buffer_size, int p_mode) { + PackedByteArray decompressed; + Compression::Mode mode = (Compression::Mode)(p_mode); + + int64_t buffer_size = p_buffer_size; + + if (buffer_size <= 0) { + ERR_FAIL_V_MSG(decompressed, "Decompression buffer size must be greater than zero."); + } + + decompressed.resize(buffer_size); + int result = Compression::decompress(decompressed.ptrw(), buffer_size, p_instance->ptr(), p_instance->size(), mode); + + result = result >= 0 ? result : 0; + decompressed.resize(result); + + return decompressed; + } + + static PackedByteArray func_PackedByteArray_decompress_dynamic(PackedByteArray *p_instance, int64_t p_buffer_size, int p_mode) { + PackedByteArray decompressed; + int64_t max_output_size = p_buffer_size; + Compression::Mode mode = (Compression::Mode)(p_mode); + + int result = Compression::decompress_dynamic(&decompressed, max_output_size, p_instance->ptr(), p_instance->size(), mode); + + if (result == OK) { + return decompressed; + } else { + decompressed.clear(); + ERR_FAIL_V_MSG(decompressed, "Decompression failed."); + } + } + + static String func_PackedByteArray_hex_encode(PackedByteArray *p_instance) { + if (p_instance->size() == 0) { + return String(); + } + const uint8_t *r = p_instance->ptr(); + String s = String::hex_encode_buffer(&r[0], p_instance->size()); + return s; + } + + static void func_Callable_call(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { + Callable *callable = VariantGetInternalPtr<Callable>::get_ptr(v); + callable->call(p_args, p_argcount, r_ret, r_error); + } + + static void func_Callable_call_deferred(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { + Callable *callable = VariantGetInternalPtr<Callable>::get_ptr(v); + callable->call_deferred(p_args, p_argcount); + } + + static void func_Callable_bind(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { + Callable *callable = VariantGetInternalPtr<Callable>::get_ptr(v); + r_ret = callable->bind(p_args, p_argcount); + } + + static void func_Signal_emit(Variant *v, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { + Signal *signal = VariantGetInternalPtr<Signal>::get_ptr(v); + signal->emit(p_args, p_argcount); + } + + struct ConstantData { + Map<StringName, int> value; +#ifdef DEBUG_ENABLED + List<StringName> value_ordered; +#endif + Map<StringName, Variant> variant_value; +#ifdef DEBUG_ENABLED + List<StringName> variant_value_ordered; +#endif + }; + + static ConstantData *constant_data; + + static void add_constant(int p_type, StringName p_constant_name, int 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) { + 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); +#endif + } +}; + +_VariantCall::ConstantData *_VariantCall::constant_data = nullptr; + +struct VariantBuiltInMethodInfo { + void (*call)(Variant *base, const Variant **p_args, int p_argcount, Variant &r_ret, const Vector<Variant> &p_defvals, Callable::CallError &r_error); + Variant::ValidatedBuiltInMethod validated_call; + Variant::PTRBuiltInMethod ptrcall; + + Vector<Variant> default_arguments; + Vector<String> argument_names; + + bool is_const; + bool has_return_type; + bool is_vararg; + Variant::Type return_type; + int argument_count; + Variant::Type (*get_argument_type)(int p_arg); +}; + +typedef OAHashMap<StringName, VariantBuiltInMethodInfo> BuiltinMethodMap; +static BuiltinMethodMap *builtin_method_info; +static List<StringName> *builtin_method_names; + +template <class T> +static void register_builtin_method(const Vector<String> &p_argnames, const Vector<Variant> &p_def_args) { + StringName name = T::get_name(); + + ERR_FAIL_COND(builtin_method_info[T::get_base_type()].has(name)); + + VariantBuiltInMethodInfo imi; + + imi.call = T::call; + imi.validated_call = T::validated_call; + if (T::is_vararg()) { + imi.ptrcall = nullptr; + } else { + imi.ptrcall = T::ptrcall; + } + + imi.default_arguments = p_def_args; + imi.argument_names = p_argnames; + + imi.is_const = T::is_const(); + imi.is_vararg = T::is_vararg(); + imi.has_return_type = T::has_return_type(); + imi.return_type = T::get_return_type(); + imi.argument_count = T::get_argument_count(); + imi.get_argument_type = T::get_argument_type; +#ifdef DEBUG_METHODS_ENABLED + ERR_FAIL_COND(!imi.is_vararg && imi.argument_count != imi.argument_names.size()); +#endif + + builtin_method_info[T::get_base_type()].insert(name, imi); + builtin_method_names[T::get_base_type()].push_back(name); +} + +void Variant::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) { + if (type == Variant::OBJECT) { + //call object + Object *obj = _get_obj().obj; + if (!obj) { + r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; + return; + } +#ifdef DEBUG_ENABLED + if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { + r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; + return; + } + +#endif + r_ret = _get_obj().obj->call(p_method, p_args, p_argcount, r_error); + + //else if (type==Variant::METHOD) { + } else { + r_error.error = Callable::CallError::CALL_OK; + + const VariantBuiltInMethodInfo *imf = builtin_method_info[type].lookup_ptr(p_method); + + if (!imf) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + return; + } + + imf->call(this, p_args, p_argcount, r_ret, imf->default_arguments, r_error); + } +} + +bool Variant::has_method(const StringName &p_method) const { + if (type == OBJECT) { + Object *obj = get_validated_object(); + if (!obj) { + return false; + } + + return obj->has_method(p_method); + } + + return builtin_method_info[type].has(p_method); +} + +bool Variant::has_builtin_method(Variant::Type p_type, const StringName &p_method) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); + return builtin_method_info[p_type].has(p_method); +} + +Variant::ValidatedBuiltInMethod Variant::get_validated_builtin_method(Variant::Type p_type, const StringName &p_method) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); + ERR_FAIL_COND_V(!method, nullptr); + return method->validated_call; +} + +Variant::PTRBuiltInMethod Variant::get_ptr_builtin_method(Variant::Type p_type, const StringName &p_method) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); + ERR_FAIL_COND_V(!method, nullptr); + return method->ptrcall; +} + +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); + ERR_FAIL_COND_V(!method, 0); + return method->argument_count; +} + +Variant::Type Variant::get_builtin_method_argument_type(Variant::Type p_type, const StringName &p_method, int p_argument) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::NIL); + const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); + ERR_FAIL_COND_V(!method, Variant::NIL); + ERR_FAIL_INDEX_V(p_argument, method->argument_count, Variant::NIL); + return method->get_argument_type(p_argument); +} + +String Variant::get_builtin_method_argument_name(Variant::Type p_type, const StringName &p_method, int p_argument) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, String()); + const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); + ERR_FAIL_COND_V(!method, String()); +#ifdef DEBUG_METHODS_ENABLED + ERR_FAIL_INDEX_V(p_argument, method->argument_count, String()); + return method->argument_names[p_argument]; +#else + return "arg" + itos(p_argument + 1); +#endif +} + +Vector<Variant> Variant::get_builtin_method_default_arguments(Variant::Type p_type, const StringName &p_method) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Vector<Variant>()); + const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); + ERR_FAIL_COND_V(!method, Vector<Variant>()); + return method->default_arguments; +} + +bool Variant::has_builtin_method_return_value(Variant::Type p_type, const StringName &p_method) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); + const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); + ERR_FAIL_COND_V(!method, false); + return method->has_return_type; +} + +void Variant::get_builtin_method_list(Variant::Type p_type, List<StringName> *p_list) { + ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX); + for (List<StringName>::Element *E = builtin_method_names[p_type].front(); E; E = E->next()) { + p_list->push_back(E->get()); + } +} + +int Variant::get_builtin_method_count(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1); + return builtin_method_names[p_type].size(); +} + +Variant::Type Variant::get_builtin_method_return_type(Variant::Type p_type, const StringName &p_method) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::NIL); + const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); + ERR_FAIL_COND_V(!method, Variant::NIL); + return method->return_type; +} + +bool Variant::is_builtin_method_const(Variant::Type p_type, const StringName &p_method) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); + const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); + ERR_FAIL_COND_V(!method, false); + return method->is_const; +} + +bool Variant::is_builtin_method_vararg(Variant::Type p_type, const StringName &p_method) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); + const VariantBuiltInMethodInfo *method = builtin_method_info[p_type].lookup_ptr(p_method); + ERR_FAIL_COND_V(!method, false); + return method->is_vararg; +} + +void Variant::get_method_list(List<MethodInfo> *p_list) const { + if (type == OBJECT) { + Object *obj = get_validated_object(); + if (obj) { + obj->get_method_list(p_list); + } + } else { + for (List<StringName>::Element *E = builtin_method_names[type].front(); E; E = E->next()) { + const VariantBuiltInMethodInfo *method = builtin_method_info[type].lookup_ptr(E->get()); + ERR_CONTINUE(!method); + + MethodInfo mi; + mi.name = E->get(); + + //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; + } + + 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); + } + } +} + +void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants) { + ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX); + + _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type]; + +#ifdef DEBUG_ENABLED + for (List<StringName>::Element *E = cd.value_ordered.front(); E; E = E->next()) { + p_constants->push_back(E->get()); +#else + for (Map<StringName, int>::Element *E = cd.value.front(); E; E = E->next()) { + p_constants->push_back(E->key()); +#endif + } + +#ifdef DEBUG_ENABLED + for (List<StringName>::Element *E = cd.variant_value_ordered.front(); E; E = E->next()) { + p_constants->push_back(E->get()); +#else + for (Map<StringName, Variant>::Element *E = cd.variant_value.front(); E; E = E->next()) { + p_constants->push_back(E->key()); +#endif + } +} + +int Variant::get_constants_count_for_type(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1); + _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type]; + + return cd.value.size() + cd.variant_value.size(); +} + +bool Variant::has_constant(Variant::Type p_type, const StringName &p_value) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); + _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type]; + return cd.value.has(p_value) || cd.variant_value.has(p_value); +} + +Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_value, bool *r_valid) { + if (r_valid) { + *r_valid = false; + } + + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0); + _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type]; + + Map<StringName, int>::Element *E = cd.value.find(p_value); + if (!E) { + Map<StringName, Variant>::Element *F = cd.variant_value.find(p_value); + if (F) { + if (r_valid) { + *r_valid = true; + } + return F->get(); + } else { + return -1; + } + } + if (r_valid) { + *r_valid = true; + } + + return E->get(); +} + +#ifdef DEBUG_METHODS_ENABLED +#define bind_method(m_type, m_method, m_arg_names, m_default_args) \ + METHOD_CLASS(m_type, m_method, &m_type::m_method); \ + register_builtin_method<Method_##m_type##_##m_method>(m_arg_names, m_default_args); +#else +#define bind_method(m_type, m_method, m_arg_names, m_default_args) \ + METHOD_CLASS(m_type, m_method, &m_type ::m_method); \ + register_builtin_method<Method_##m_type##_##m_method>(sarray(), m_default_args); +#endif + +#ifdef DEBUG_METHODS_ENABLED +#define bind_methodv(m_type, m_name, m_method, m_arg_names, m_default_args) \ + METHOD_CLASS(m_type, m_name, m_method); \ + register_builtin_method<Method_##m_type##_##m_name>(m_arg_names, m_default_args); +#else +#define bind_methodv(m_type, m_name, m_method, m_arg_names, m_default_args) \ + METHOD_CLASS(m_type, m_name, m_method); \ + register_builtin_method<Method_##m_type##_##m_name>(sarray(), m_default_args); +#endif + +#ifdef DEBUG_METHODS_ENABLED +#define bind_function(m_type, m_name, m_method, m_arg_names, m_default_args) \ + FUNCTION_CLASS(m_type, m_name, m_method); \ + register_builtin_method<Method_##m_type##_##m_name>(m_arg_names, m_default_args); +#else +#define bind_function(m_type, m_name, m_method, m_arg_names, m_default_args) \ + FUNCTION_CLASS(m_type, m_name, m_method); \ + register_builtin_method<Method_##m_type##_##m_name>(sarray(), m_default_args); +#endif + +#define bind_custom(m_type, m_name, m_method, m_has_return, m_ret_type) \ + VARARG_CLASS(m_type, m_name, m_method, m_has_return, m_ret_type) \ + register_builtin_method<Method_##m_type##_##m_name>(sarray(), Vector<Variant>()); + +static void _register_variant_builtin_methods() { + _VariantCall::constant_data = memnew_arr(_VariantCall::ConstantData, Variant::VARIANT_MAX); + builtin_method_info = memnew_arr(BuiltinMethodMap, Variant::VARIANT_MAX); + builtin_method_names = memnew_arr(List<StringName>, Variant::VARIANT_MAX); + + /* String */ + + bind_method(String, casecmp_to, sarray("to"), varray()); + bind_method(String, nocasecmp_to, sarray("to"), varray()); + bind_method(String, naturalnocasecmp_to, sarray("to"), varray()); + bind_method(String, length, sarray(), varray()); + bind_method(String, substr, sarray("from", "len"), varray(-1)); + bind_methodv(String, find, static_cast<int (String::*)(const String &, int) const>(&String::find), sarray("what", "from"), varray(0)); + bind_method(String, count, sarray("what", "from", "to"), varray(0, 0)); + bind_method(String, countn, sarray("what", "from", "to"), varray(0, 0)); + bind_method(String, findn, sarray("what", "from"), varray(0)); + bind_method(String, rfind, sarray("what", "from"), varray(-1)); + bind_method(String, rfindn, sarray("what", "from"), varray(-1)); + bind_method(String, match, sarray("expr"), varray()); + bind_method(String, matchn, sarray("expr"), varray()); + bind_methodv(String, begins_with, static_cast<bool (String::*)(const String &) const>(&String::begins_with), sarray("text"), varray()); + bind_method(String, ends_with, sarray("text"), varray()); + bind_method(String, is_subsequence_of, sarray("text"), varray()); + bind_method(String, is_subsequence_ofi, sarray("text"), varray()); + bind_method(String, bigrams, sarray(), varray()); + bind_method(String, similarity, sarray("text"), varray()); + + bind_method(String, format, sarray("values", "placeholder"), varray("{_}")); + bind_methodv(String, replace, static_cast<String (String::*)(const String &, const String &) const>(&String::replace), sarray("what", "forwhat"), varray()); + bind_method(String, replacen, sarray("what", "forwhat"), varray()); + bind_method(String, repeat, sarray("count"), varray()); + bind_method(String, insert, sarray("position", "what"), varray()); + bind_method(String, capitalize, sarray(), varray()); + bind_method(String, split, sarray("delimiter", "allow_empty", "maxsplit"), varray(true, 0)); + bind_method(String, rsplit, sarray("delimiter", "allow_empty", "maxsplit"), varray(true, 0)); + bind_method(String, split_floats, sarray("delimiter", "allow_empty"), varray(true)); + bind_method(String, join, sarray("parts"), varray()); + + bind_method(String, to_upper, sarray(), varray()); + bind_method(String, to_lower, sarray(), varray()); + + bind_method(String, left, sarray("position"), varray()); + bind_method(String, right, sarray("position"), varray()); + + bind_method(String, strip_edges, sarray("left", "right"), varray(true, true)); + bind_method(String, strip_escapes, sarray(), varray()); + bind_method(String, lstrip, sarray("chars"), varray()); + bind_method(String, rstrip, sarray("chars"), varray()); + bind_method(String, get_extension, sarray(), varray()); + bind_method(String, get_basename, sarray(), varray()); + bind_method(String, plus_file, sarray("file"), varray()); + bind_method(String, ord_at, sarray("at"), varray()); + bind_method(String, dedent, sarray(), varray()); + // FIXME: String needs to be immutable when binding + //bind_method(String, erase, sarray("position", "chars"), varray()); + bind_method(String, hash, sarray(), varray()); + bind_method(String, md5_text, sarray(), varray()); + bind_method(String, sha1_text, sarray(), varray()); + bind_method(String, sha256_text, sarray(), varray()); + bind_method(String, md5_buffer, sarray(), varray()); + bind_method(String, sha1_buffer, sarray(), varray()); + bind_method(String, sha256_buffer, sarray(), varray()); + bind_method(String, is_empty, sarray(), varray()); + // FIXME: Static function, not sure how to bind + //bind_method(String, humanize_size, sarray("size"), varray()); + + bind_method(String, is_abs_path, sarray(), varray()); + bind_method(String, is_rel_path, sarray(), varray()); + bind_method(String, get_base_dir, sarray(), varray()); + bind_method(String, get_file, sarray(), varray()); + bind_method(String, xml_escape, sarray("escape_quotes"), varray(false)); + bind_method(String, xml_unescape, sarray(), varray()); + bind_method(String, http_escape, sarray(), varray()); + bind_method(String, http_unescape, sarray(), varray()); + bind_method(String, c_escape, sarray(), varray()); + bind_method(String, c_unescape, sarray(), varray()); + bind_method(String, json_escape, sarray(), varray()); + bind_method(String, percent_encode, sarray(), varray()); + bind_method(String, percent_decode, sarray(), varray()); + + bind_method(String, is_valid_identifier, sarray(), varray()); + bind_method(String, is_valid_integer, sarray(), varray()); + bind_method(String, is_valid_float, sarray(), varray()); + bind_method(String, is_valid_hex_number, sarray("with_prefix"), varray(false)); + bind_method(String, is_valid_html_color, sarray(), varray()); + bind_method(String, is_valid_ip_address, sarray(), varray()); + bind_method(String, is_valid_filename, sarray(), varray()); + + bind_method(String, to_int, sarray(), varray()); + bind_method(String, to_float, sarray(), varray()); + bind_method(String, hex_to_int, sarray("with_prefix"), varray(true)); + bind_method(String, bin_to_int, sarray("with_prefix"), varray(true)); + + bind_method(String, lpad, sarray("min_length", "character"), varray(" ")); + bind_method(String, rpad, sarray("min_length", "character"), varray(" ")); + bind_method(String, pad_decimals, sarray("digits"), varray()); + bind_method(String, pad_zeros, sarray("digits"), varray()); + bind_method(String, trim_prefix, sarray("prefix"), varray()); + bind_method(String, trim_suffix, sarray("suffix"), varray()); + + bind_method(String, to_ascii_buffer, sarray(), varray()); + bind_method(String, to_utf8_buffer, sarray(), varray()); + bind_method(String, to_utf16_buffer, sarray(), varray()); + bind_method(String, to_utf32_buffer, sarray(), varray()); + + /* Vector2 */ + + bind_method(Vector2, angle, sarray(), varray()); + bind_method(Vector2, angle_to, sarray("to"), varray()); + bind_method(Vector2, angle_to_point, sarray("to"), varray()); + bind_method(Vector2, direction_to, sarray("b"), varray()); + bind_method(Vector2, distance_to, sarray("to"), varray()); + bind_method(Vector2, distance_squared_to, sarray("to"), varray()); + bind_method(Vector2, length, sarray(), varray()); + bind_method(Vector2, length_squared, sarray(), varray()); + bind_method(Vector2, normalized, sarray(), varray()); + bind_method(Vector2, is_normalized, sarray(), varray()); + bind_method(Vector2, is_equal_approx, sarray("to"), varray()); + bind_method(Vector2, posmod, sarray("mod"), varray()); + bind_method(Vector2, posmodv, sarray("modv"), varray()); + bind_method(Vector2, project, sarray("b"), varray()); + bind_method(Vector2, lerp, sarray("to", "weight"), varray()); + bind_method(Vector2, slerp, sarray("to", "weight"), varray()); + bind_method(Vector2, cubic_interpolate, sarray("b", "pre_a", "post_b", "weight"), varray()); + bind_method(Vector2, move_toward, sarray("to", "delta"), varray()); + bind_method(Vector2, rotated, sarray("phi"), varray()); + bind_method(Vector2, orthogonal, sarray(), varray()); + bind_method(Vector2, floor, sarray(), varray()); + bind_method(Vector2, ceil, sarray(), varray()); + bind_method(Vector2, round, sarray(), varray()); + bind_method(Vector2, aspect, sarray(), varray()); + bind_method(Vector2, dot, sarray("with"), varray()); + bind_method(Vector2, slide, sarray("n"), varray()); + bind_method(Vector2, bounce, sarray("n"), varray()); + bind_method(Vector2, reflect, sarray("n"), varray()); + bind_method(Vector2, cross, sarray("with"), varray()); + bind_method(Vector2, abs, sarray(), varray()); + bind_method(Vector2, sign, sarray(), varray()); + bind_method(Vector2, snapped, sarray("step"), varray()); + bind_method(Vector2, clamped, sarray("length"), varray()); + + /* Vector2i */ + + bind_method(Vector2i, aspect, sarray(), varray()); + bind_method(Vector2i, sign, sarray(), varray()); + bind_method(Vector2i, abs, sarray(), varray()); + + /* Rect2 */ + + bind_method(Rect2, get_area, sarray(), varray()); + bind_method(Rect2, has_no_area, sarray(), varray()); + bind_method(Rect2, has_point, sarray("point"), varray()); + bind_method(Rect2, is_equal_approx, sarray("rect"), varray()); + bind_method(Rect2, intersects, sarray("b", "include_borders"), varray(false)); + bind_method(Rect2, encloses, sarray("b"), varray()); + bind_method(Rect2, intersection, sarray("b"), varray()); + bind_method(Rect2, merge, sarray("b"), varray()); + bind_method(Rect2, expand, sarray("to"), varray()); + bind_method(Rect2, grow, sarray("amount"), varray()); + bind_methodv(Rect2, grow_side, &Rect2::grow_side_bind, sarray("side", "amount"), varray()); + bind_method(Rect2, grow_individual, sarray("left", "top", "right", "bottom"), varray()); + bind_method(Rect2, abs, sarray(), varray()); + + /* Rect2i */ + + bind_method(Rect2i, get_area, sarray(), varray()); + bind_method(Rect2i, has_no_area, sarray(), varray()); + bind_method(Rect2i, has_point, sarray("point"), varray()); + bind_method(Rect2i, intersects, sarray("b"), varray()); + bind_method(Rect2i, encloses, sarray("b"), varray()); + bind_method(Rect2i, intersection, sarray("b"), varray()); + bind_method(Rect2i, merge, sarray("b"), varray()); + bind_method(Rect2i, expand, sarray("to"), varray()); + bind_method(Rect2i, grow, sarray("amount"), varray()); + bind_methodv(Rect2i, grow_side, &Rect2i::grow_side_bind, sarray("side", "amount"), varray()); + bind_method(Rect2i, grow_individual, sarray("left", "top", "right", "bottom"), varray()); + bind_method(Rect2i, abs, sarray(), varray()); + + /* Vector3 */ + + bind_method(Vector3, min_axis, sarray(), varray()); + bind_method(Vector3, max_axis, sarray(), varray()); + bind_method(Vector3, angle_to, sarray("to"), varray()); + bind_method(Vector3, direction_to, sarray("b"), varray()); + bind_method(Vector3, distance_to, sarray("b"), varray()); + bind_method(Vector3, distance_squared_to, sarray("b"), varray()); + bind_method(Vector3, length, sarray(), varray()); + bind_method(Vector3, length_squared, sarray(), varray()); + bind_method(Vector3, normalized, sarray(), varray()); + bind_method(Vector3, is_normalized, sarray(), varray()); + bind_method(Vector3, is_equal_approx, sarray("to"), varray()); + bind_method(Vector3, inverse, sarray(), varray()); + bind_method(Vector3, snapped, sarray("step"), varray()); + bind_method(Vector3, rotated, sarray("by_axis", "phi"), varray()); + bind_method(Vector3, lerp, sarray("to", "weight"), varray()); + bind_method(Vector3, slerp, sarray("to", "weight"), varray()); + bind_method(Vector3, cubic_interpolate, sarray("b", "pre_a", "post_b", "weight"), varray()); + bind_method(Vector3, move_toward, sarray("to", "delta"), varray()); + bind_method(Vector3, dot, sarray("with"), varray()); + bind_method(Vector3, cross, sarray("with"), varray()); + bind_method(Vector3, outer, sarray("with"), varray()); + bind_method(Vector3, to_diagonal_matrix, sarray(), varray()); + bind_method(Vector3, abs, sarray(), varray()); + bind_method(Vector3, floor, sarray(), varray()); + bind_method(Vector3, ceil, sarray(), varray()); + bind_method(Vector3, round, sarray(), varray()); + bind_method(Vector3, posmod, sarray("mod"), varray()); + bind_method(Vector3, posmodv, sarray("modv"), varray()); + bind_method(Vector3, project, sarray("b"), varray()); + bind_method(Vector3, slide, sarray("n"), varray()); + bind_method(Vector3, bounce, sarray("n"), varray()); + bind_method(Vector3, reflect, sarray("n"), varray()); + bind_method(Vector3, sign, sarray(), varray()); + + /* Vector3i */ + + bind_method(Vector3i, min_axis, sarray(), varray()); + bind_method(Vector3i, max_axis, sarray(), varray()); + bind_method(Vector3i, sign, sarray(), varray()); + bind_method(Vector3i, abs, sarray(), varray()); + + /* Plane */ + + bind_method(Plane, normalized, sarray(), varray()); + bind_method(Plane, center, sarray(), varray()); + bind_method(Plane, is_equal_approx, sarray("to_plane"), varray()); + bind_method(Plane, is_point_over, sarray("plane"), varray()); + bind_method(Plane, distance_to, sarray("point"), varray()); + bind_method(Plane, has_point, sarray("point", "epsilon"), varray(CMP_EPSILON)); + bind_method(Plane, project, sarray("point"), varray()); + bind_methodv(Plane, intersect_3, &Plane::intersect_3_bind, sarray("b", "c"), varray()); + bind_methodv(Plane, intersects_ray, &Plane::intersects_ray_bind, sarray("from", "dir"), varray()); + bind_methodv(Plane, intersects_segment, &Plane::intersects_segment_bind, sarray("from", "to"), varray()); + + /* Quat */ + + bind_method(Quat, length, sarray(), varray()); + bind_method(Quat, length_squared, sarray(), varray()); + bind_method(Quat, normalized, sarray(), varray()); + bind_method(Quat, is_normalized, sarray(), varray()); + bind_method(Quat, is_equal_approx, sarray("to"), varray()); + bind_method(Quat, inverse, sarray(), varray()); + bind_method(Quat, dot, sarray("with"), varray()); + bind_method(Quat, slerp, sarray("to", "weight"), varray()); + bind_method(Quat, slerpni, sarray("to", "weight"), varray()); + bind_method(Quat, cubic_slerp, sarray("b", "pre_a", "post_b", "weight"), varray()); + bind_method(Quat, get_euler, sarray(), varray()); + + // FIXME: Quat is atomic, this should be done via construcror + //ADDFUNC1(QUAT, NIL, Quat, set_euler, VECTOR3, "euler", varray()); + //ADDFUNC2(QUAT, NIL, Quat, set_axis_angle, VECTOR3, "axis", FLOAT, "angle", varray()); + + /* Color */ + + bind_method(Color, to_argb32, sarray(), varray()); + bind_method(Color, to_abgr32, sarray(), varray()); + bind_method(Color, to_rgba32, sarray(), varray()); + bind_method(Color, to_argb64, sarray(), varray()); + bind_method(Color, to_abgr64, sarray(), varray()); + bind_method(Color, to_rgba64, sarray(), varray()); + + bind_method(Color, inverted, sarray(), varray()); + bind_method(Color, lerp, sarray("to", "weight"), varray()); + bind_method(Color, lightened, sarray("amount"), varray()); + bind_method(Color, darkened, sarray("amount"), varray()); + bind_method(Color, to_html, sarray("with_alpha"), varray(true)); + bind_method(Color, blend, sarray("over"), varray()); + + // FIXME: Color is immutable, need to probably find a way to do this via constructor + //ADDFUNC4R(COLOR, COLOR, Color, from_hsv, FLOAT, "h", FLOAT, "s", FLOAT, "v", FLOAT, "a", varray(1.0)); + bind_method(Color, is_equal_approx, sarray("to"), varray()); + + /* RID */ + + bind_method(RID, get_id, sarray(), varray()); + + /* NodePath */ + + bind_method(NodePath, is_absolute, sarray(), varray()); + bind_method(NodePath, get_name_count, sarray(), varray()); + bind_method(NodePath, get_name, sarray("idx"), varray()); + bind_method(NodePath, get_subname_count, sarray(), varray()); + bind_method(NodePath, get_subname, sarray("idx"), varray()); + bind_method(NodePath, get_concatenated_subnames, sarray(), varray()); + bind_method(NodePath, get_as_property_path, sarray(), varray()); + bind_method(NodePath, is_empty, sarray(), varray()); + + /* Callable */ + + bind_method(Callable, is_null, sarray(), varray()); + bind_method(Callable, is_custom, sarray(), varray()); + bind_method(Callable, is_standard, sarray(), varray()); + bind_method(Callable, get_object, sarray(), varray()); + bind_method(Callable, get_object_id, sarray(), varray()); + bind_method(Callable, get_method, sarray(), varray()); + bind_method(Callable, hash, sarray(), varray()); + bind_method(Callable, unbind, sarray("argcount"), varray()); + + bind_custom(Callable, call, _VariantCall::func_Callable_call, true, Variant); + bind_custom(Callable, call_deferred, _VariantCall::func_Callable_call_deferred, false, Variant); + bind_custom(Callable, bind, _VariantCall::func_Callable_bind, true, Callable); + + /* Signal */ + + bind_method(Signal, is_null, sarray(), varray()); + bind_method(Signal, get_object, sarray(), varray()); + bind_method(Signal, get_object_id, sarray(), varray()); + bind_method(Signal, get_name, sarray(), varray()); + + bind_method(Signal, connect, sarray("callable", "binds", "flags"), varray(Array(), 0)); + bind_method(Signal, disconnect, sarray("callable"), varray()); + bind_method(Signal, is_connected, sarray("callable"), varray()); + bind_method(Signal, get_connections, sarray(), varray()); + + bind_custom(Signal, emit, _VariantCall::func_Signal_emit, false, Variant); + + /* Transform2D */ + + bind_method(Transform2D, inverse, sarray(), varray()); + bind_method(Transform2D, affine_inverse, sarray(), varray()); + bind_method(Transform2D, get_rotation, sarray(), varray()); + bind_method(Transform2D, get_origin, sarray(), varray()); + bind_method(Transform2D, get_scale, sarray(), varray()); + bind_method(Transform2D, orthonormalized, sarray(), varray()); + bind_method(Transform2D, rotated, sarray("phi"), varray()); + bind_method(Transform2D, scaled, sarray("scale"), varray()); + bind_method(Transform2D, translated, sarray("offset"), varray()); + bind_method(Transform2D, basis_xform, sarray("v"), varray()); + bind_method(Transform2D, basis_xform_inv, sarray("v"), varray()); + bind_method(Transform2D, interpolate_with, sarray("xform", "weight"), varray()); + bind_method(Transform2D, is_equal_approx, sarray("xform"), varray()); + + /* Basis */ + + bind_method(Basis, inverse, sarray(), varray()); + bind_method(Basis, transposed, sarray(), varray()); + bind_method(Basis, orthonormalized, sarray(), varray()); + bind_method(Basis, determinant, sarray(), varray()); + bind_methodv(Basis, rotated, static_cast<Basis (Basis::*)(const Vector3 &, float) const>(&Basis::rotated), sarray("axis", "phi"), varray()); + bind_method(Basis, scaled, sarray("scale"), varray()); + bind_method(Basis, get_scale, sarray(), varray()); + bind_method(Basis, get_euler, sarray(), varray()); + bind_method(Basis, tdotx, sarray("with"), varray()); + bind_method(Basis, tdoty, sarray("with"), varray()); + bind_method(Basis, tdotz, sarray("with"), varray()); + bind_method(Basis, get_orthogonal_index, sarray(), varray()); + bind_method(Basis, slerp, sarray("to", "weight"), varray()); + bind_method(Basis, is_equal_approx, sarray("b"), varray()); + bind_method(Basis, get_rotation_quat, sarray(), varray()); + + /* AABB */ + + bind_method(AABB, abs, sarray(), varray()); + bind_method(AABB, get_area, sarray(), varray()); + bind_method(AABB, has_no_area, sarray(), varray()); + bind_method(AABB, has_no_surface, sarray(), varray()); + bind_method(AABB, has_point, sarray("point"), varray()); + bind_method(AABB, is_equal_approx, sarray("aabb"), varray()); + bind_method(AABB, intersects, sarray("with"), varray()); + bind_method(AABB, encloses, sarray("with"), varray()); + bind_method(AABB, intersects_plane, sarray("plane"), varray()); + bind_method(AABB, intersection, sarray("with"), varray()); + bind_method(AABB, merge, sarray("with"), varray()); + bind_method(AABB, expand, sarray("to_point"), varray()); + bind_method(AABB, grow, sarray("by"), varray()); + bind_method(AABB, get_support, sarray("dir"), varray()); + bind_method(AABB, get_longest_axis, sarray(), varray()); + bind_method(AABB, get_longest_axis_index, sarray(), varray()); + bind_method(AABB, get_longest_axis_size, sarray(), varray()); + bind_method(AABB, get_shortest_axis, sarray(), varray()); + bind_method(AABB, get_shortest_axis_index, sarray(), varray()); + bind_method(AABB, get_shortest_axis_size, sarray(), varray()); + bind_method(AABB, get_endpoint, sarray("idx"), varray()); + bind_methodv(AABB, intersects_segment, &AABB::intersects_segment_bind, sarray("from", "to"), varray()); + bind_methodv(AABB, intersects_ray, &AABB::intersects_ray_bind, sarray("from", "dir"), varray()); + + /* Transform */ + + bind_method(Transform, inverse, sarray(), varray()); + bind_method(Transform, affine_inverse, sarray(), varray()); + bind_method(Transform, orthonormalized, sarray(), varray()); + bind_method(Transform, rotated, sarray("axis", "phi"), varray()); + bind_method(Transform, scaled, sarray("scale"), varray()); + bind_method(Transform, translated, sarray("offset"), varray()); + bind_method(Transform, looking_at, sarray("target", "up"), varray()); + bind_method(Transform, interpolate_with, sarray("xform", "weight"), varray()); + bind_method(Transform, is_equal_approx, sarray("xform"), varray()); + + /* Dictionary */ + + bind_method(Dictionary, size, sarray(), varray()); + bind_method(Dictionary, is_empty, sarray(), varray()); + bind_method(Dictionary, clear, sarray(), varray()); + bind_method(Dictionary, has, sarray("key"), varray()); + bind_method(Dictionary, has_all, sarray("keys"), varray()); + bind_method(Dictionary, erase, sarray("key"), varray()); + bind_method(Dictionary, hash, sarray(), varray()); + bind_method(Dictionary, keys, sarray(), varray()); + bind_method(Dictionary, values, sarray(), varray()); + bind_method(Dictionary, duplicate, sarray("deep"), varray(false)); + bind_method(Dictionary, get, sarray("key", "default"), varray(Variant())); + + /* Array */ + + bind_method(Array, size, sarray(), varray()); + bind_method(Array, is_empty, sarray(), varray()); + bind_method(Array, clear, sarray(), varray()); + bind_method(Array, hash, sarray(), varray()); + bind_method(Array, push_back, sarray("value"), varray()); + bind_method(Array, push_front, sarray("value"), varray()); + bind_method(Array, append, sarray("value"), varray()); + bind_method(Array, append_array, sarray("array"), varray()); + bind_method(Array, resize, sarray("size"), varray()); + bind_method(Array, insert, sarray("position", "value"), varray()); + bind_method(Array, remove, sarray("position"), varray()); + bind_method(Array, erase, sarray("value"), varray()); + bind_method(Array, front, sarray(), varray()); + bind_method(Array, back, sarray(), varray()); + bind_method(Array, find, sarray("what", "from"), varray(0)); + bind_method(Array, rfind, sarray("what", "from"), varray(-1)); + bind_method(Array, find_last, sarray("value"), varray()); + bind_method(Array, count, sarray("value"), varray()); + bind_method(Array, has, sarray("value"), varray()); + bind_method(Array, pop_back, sarray(), varray()); + bind_method(Array, pop_front, sarray(), varray()); + bind_method(Array, sort, sarray(), varray()); + bind_method(Array, sort_custom, sarray("obj", "func"), varray()); + bind_method(Array, shuffle, sarray(), varray()); + bind_method(Array, bsearch, sarray("value", "before"), varray(true)); + bind_method(Array, bsearch_custom, sarray("value", "obj", "func", "before"), varray(true)); + bind_method(Array, invert, sarray(), varray()); + bind_method(Array, duplicate, sarray("deep"), varray(false)); + bind_method(Array, slice, sarray("begin", "end", "step", "deep"), varray(1, false)); + bind_method(Array, max, sarray(), varray()); + bind_method(Array, min, sarray(), varray()); + + /* Byte Array */ + bind_method(PackedByteArray, size, sarray(), varray()); + bind_method(PackedByteArray, is_empty, sarray(), varray()); + bind_method(PackedByteArray, set, sarray("index", "value"), varray()); + bind_method(PackedByteArray, push_back, sarray("value"), varray()); + bind_method(PackedByteArray, append, sarray("value"), varray()); + bind_method(PackedByteArray, append_array, sarray("array"), varray()); + bind_method(PackedByteArray, remove, sarray("index"), varray()); + bind_method(PackedByteArray, insert, sarray("at_index", "value"), varray()); + bind_method(PackedByteArray, resize, sarray("new_size"), varray()); + bind_method(PackedByteArray, has, sarray("value"), varray()); + bind_method(PackedByteArray, invert, sarray(), varray()); + bind_method(PackedByteArray, subarray, sarray("from", "to"), varray()); + bind_method(PackedByteArray, sort, sarray(), varray()); + bind_method(PackedByteArray, duplicate, sarray(), varray()); + + bind_function(PackedByteArray, get_string_from_ascii, _VariantCall::func_PackedByteArray_get_string_from_ascii, sarray(), varray()); + bind_function(PackedByteArray, get_string_from_utf8, _VariantCall::func_PackedByteArray_get_string_from_utf8, sarray(), varray()); + bind_function(PackedByteArray, get_string_from_utf16, _VariantCall::func_PackedByteArray_get_string_from_utf16, sarray(), varray()); + bind_function(PackedByteArray, get_string_from_utf32, _VariantCall::func_PackedByteArray_get_string_from_utf32, sarray(), varray()); + bind_function(PackedByteArray, hex_encode, _VariantCall::func_PackedByteArray_hex_encode, sarray(), varray()); + bind_function(PackedByteArray, compress, _VariantCall::func_PackedByteArray_compress, sarray("compression_mode"), varray(0)); + bind_function(PackedByteArray, decompress, _VariantCall::func_PackedByteArray_decompress, sarray("buffer_size", "compression_mode"), varray(0)); + bind_function(PackedByteArray, decompress_dynamic, _VariantCall::func_PackedByteArray_decompress_dynamic, sarray("max_output_size", "compression_mode"), varray(0)); + + /* Int32 Array */ + + bind_method(PackedInt32Array, size, sarray(), varray()); + bind_method(PackedInt32Array, is_empty, sarray(), varray()); + bind_method(PackedInt32Array, set, sarray("index", "value"), varray()); + bind_method(PackedInt32Array, push_back, sarray("value"), varray()); + bind_method(PackedInt32Array, append, sarray("value"), varray()); + bind_method(PackedInt32Array, append_array, sarray("array"), varray()); + bind_method(PackedInt32Array, remove, sarray("index"), varray()); + bind_method(PackedInt32Array, insert, sarray("at_index", "value"), varray()); + bind_method(PackedInt32Array, resize, sarray("new_size"), varray()); + bind_method(PackedInt32Array, has, sarray("value"), varray()); + bind_method(PackedInt32Array, invert, sarray(), varray()); + bind_method(PackedInt32Array, subarray, sarray("from", "to"), varray()); + bind_method(PackedInt32Array, to_byte_array, sarray(), varray()); + bind_method(PackedInt32Array, sort, sarray(), varray()); + bind_method(PackedInt32Array, duplicate, sarray(), varray()); + + /* Int64 Array */ + + bind_method(PackedInt64Array, size, sarray(), varray()); + bind_method(PackedInt64Array, is_empty, sarray(), varray()); + bind_method(PackedInt64Array, set, sarray("index", "value"), varray()); + bind_method(PackedInt64Array, push_back, sarray("value"), varray()); + bind_method(PackedInt64Array, append, sarray("value"), varray()); + bind_method(PackedInt64Array, append_array, sarray("array"), varray()); + bind_method(PackedInt64Array, remove, sarray("index"), varray()); + bind_method(PackedInt64Array, insert, sarray("at_index", "value"), varray()); + bind_method(PackedInt64Array, resize, sarray("new_size"), varray()); + bind_method(PackedInt64Array, has, sarray("value"), varray()); + bind_method(PackedInt64Array, invert, sarray(), varray()); + bind_method(PackedInt64Array, subarray, sarray("from", "to"), varray()); + bind_method(PackedInt64Array, to_byte_array, sarray(), varray()); + bind_method(PackedInt64Array, sort, sarray(), varray()); + bind_method(PackedInt64Array, duplicate, sarray(), varray()); + + /* Float32 Array */ + + bind_method(PackedFloat32Array, size, sarray(), varray()); + bind_method(PackedFloat32Array, is_empty, sarray(), varray()); + bind_method(PackedFloat32Array, set, sarray("index", "value"), varray()); + bind_method(PackedFloat32Array, push_back, sarray("value"), varray()); + bind_method(PackedFloat32Array, append, sarray("value"), varray()); + bind_method(PackedFloat32Array, append_array, sarray("array"), varray()); + bind_method(PackedFloat32Array, remove, sarray("index"), varray()); + bind_method(PackedFloat32Array, insert, sarray("at_index", "value"), varray()); + bind_method(PackedFloat32Array, resize, sarray("new_size"), varray()); + bind_method(PackedFloat32Array, has, sarray("value"), varray()); + bind_method(PackedFloat32Array, invert, sarray(), varray()); + bind_method(PackedFloat32Array, subarray, sarray("from", "to"), varray()); + bind_method(PackedFloat32Array, to_byte_array, sarray(), varray()); + bind_method(PackedFloat32Array, sort, sarray(), varray()); + bind_method(PackedFloat32Array, duplicate, sarray(), varray()); + + /* Float64 Array */ + + bind_method(PackedFloat64Array, size, sarray(), varray()); + bind_method(PackedFloat64Array, is_empty, sarray(), varray()); + bind_method(PackedFloat64Array, set, sarray("index", "value"), varray()); + bind_method(PackedFloat64Array, push_back, sarray("value"), varray()); + bind_method(PackedFloat64Array, append, sarray("value"), varray()); + bind_method(PackedFloat64Array, append_array, sarray("array"), varray()); + bind_method(PackedFloat64Array, remove, sarray("index"), varray()); + bind_method(PackedFloat64Array, insert, sarray("at_index", "value"), varray()); + bind_method(PackedFloat64Array, resize, sarray("new_size"), varray()); + bind_method(PackedFloat64Array, has, sarray("value"), varray()); + bind_method(PackedFloat64Array, invert, sarray(), varray()); + bind_method(PackedFloat64Array, subarray, sarray("from", "to"), varray()); + bind_method(PackedFloat64Array, to_byte_array, sarray(), varray()); + bind_method(PackedFloat64Array, sort, sarray(), varray()); + bind_method(PackedFloat64Array, duplicate, sarray(), varray()); + + /* String Array */ + + bind_method(PackedStringArray, size, sarray(), varray()); + bind_method(PackedStringArray, is_empty, sarray(), varray()); + bind_method(PackedStringArray, set, sarray("index", "value"), varray()); + bind_method(PackedStringArray, push_back, sarray("value"), varray()); + bind_method(PackedStringArray, append, sarray("value"), varray()); + bind_method(PackedStringArray, append_array, sarray("array"), varray()); + bind_method(PackedStringArray, remove, sarray("index"), varray()); + bind_method(PackedStringArray, insert, sarray("at_index", "value"), varray()); + bind_method(PackedStringArray, resize, sarray("new_size"), varray()); + bind_method(PackedStringArray, has, sarray("value"), varray()); + bind_method(PackedStringArray, invert, sarray(), varray()); + bind_method(PackedStringArray, subarray, sarray("from", "to"), varray()); + bind_method(PackedStringArray, to_byte_array, sarray(), varray()); + bind_method(PackedStringArray, sort, sarray(), varray()); + bind_method(PackedStringArray, duplicate, sarray(), varray()); + + /* Vector2 Array */ + + bind_method(PackedVector2Array, size, sarray(), varray()); + bind_method(PackedVector2Array, is_empty, sarray(), varray()); + bind_method(PackedVector2Array, set, sarray("index", "value"), varray()); + bind_method(PackedVector2Array, push_back, sarray("value"), varray()); + bind_method(PackedVector2Array, append, sarray("value"), varray()); + bind_method(PackedVector2Array, append_array, sarray("array"), varray()); + bind_method(PackedVector2Array, remove, sarray("index"), varray()); + bind_method(PackedVector2Array, insert, sarray("at_index", "value"), varray()); + bind_method(PackedVector2Array, resize, sarray("new_size"), varray()); + bind_method(PackedVector2Array, has, sarray("value"), varray()); + bind_method(PackedVector2Array, invert, sarray(), varray()); + bind_method(PackedVector2Array, subarray, sarray("from", "to"), varray()); + bind_method(PackedVector2Array, to_byte_array, sarray(), varray()); + bind_method(PackedVector2Array, sort, sarray(), varray()); + bind_method(PackedVector2Array, duplicate, sarray(), varray()); + + /* Vector3 Array */ + + bind_method(PackedVector3Array, size, sarray(), varray()); + bind_method(PackedVector3Array, is_empty, sarray(), varray()); + bind_method(PackedVector3Array, set, sarray("index", "value"), varray()); + bind_method(PackedVector3Array, push_back, sarray("value"), varray()); + bind_method(PackedVector3Array, append, sarray("value"), varray()); + bind_method(PackedVector3Array, append_array, sarray("array"), varray()); + bind_method(PackedVector3Array, remove, sarray("index"), varray()); + bind_method(PackedVector3Array, insert, sarray("at_index", "value"), varray()); + bind_method(PackedVector3Array, resize, sarray("new_size"), varray()); + bind_method(PackedVector3Array, has, sarray("value"), varray()); + bind_method(PackedVector3Array, invert, sarray(), varray()); + bind_method(PackedVector3Array, subarray, sarray("from", "to"), varray()); + bind_method(PackedVector3Array, to_byte_array, sarray(), varray()); + bind_method(PackedVector3Array, sort, sarray(), varray()); + bind_method(PackedVector3Array, duplicate, sarray(), varray()); + + /* Color Array */ + + bind_method(PackedColorArray, size, sarray(), varray()); + bind_method(PackedColorArray, is_empty, sarray(), varray()); + bind_method(PackedColorArray, set, sarray("index", "value"), varray()); + bind_method(PackedColorArray, push_back, sarray("value"), varray()); + bind_method(PackedColorArray, append, sarray("value"), varray()); + bind_method(PackedColorArray, append_array, sarray("array"), varray()); + bind_method(PackedColorArray, remove, sarray("index"), varray()); + bind_method(PackedColorArray, insert, sarray("at_index", "value"), varray()); + bind_method(PackedColorArray, resize, sarray("new_size"), varray()); + bind_method(PackedColorArray, has, sarray("value"), varray()); + bind_method(PackedColorArray, invert, sarray(), varray()); + bind_method(PackedColorArray, subarray, sarray("from", "to"), varray()); + bind_method(PackedColorArray, to_byte_array, sarray(), varray()); + bind_method(PackedColorArray, sort, sarray(), varray()); + bind_method(PackedColorArray, duplicate, sarray(), varray()); + + /* Register constants */ + + int ncc = Color::get_named_color_count(); + for (int i = 0; i < ncc; i++) { + _VariantCall::add_variant_constant(Variant::COLOR, Color::get_named_color_name(i), Color::get_named_color(i)); + } + + _VariantCall::add_constant(Variant::VECTOR3, "AXIS_X", Vector3::AXIS_X); + _VariantCall::add_constant(Variant::VECTOR3, "AXIS_Y", Vector3::AXIS_Y); + _VariantCall::add_constant(Variant::VECTOR3, "AXIS_Z", Vector3::AXIS_Z); + + _VariantCall::add_variant_constant(Variant::VECTOR3, "ZERO", Vector3(0, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "ONE", Vector3(1, 1, 1)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "INF", Vector3(Math_INF, Math_INF, Math_INF)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "LEFT", Vector3(-1, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "RIGHT", Vector3(1, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "UP", Vector3(0, 1, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "DOWN", Vector3(0, -1, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "FORWARD", Vector3(0, 0, -1)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "BACK", Vector3(0, 0, 1)); + + _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_X", Vector3i::AXIS_X); + _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Y", Vector3i::AXIS_Y); + _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Z", Vector3i::AXIS_Z); + + _VariantCall::add_variant_constant(Variant::VECTOR3I, "ZERO", Vector3i(0, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "ONE", Vector3i(1, 1, 1)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "LEFT", Vector3i(-1, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "RIGHT", Vector3i(1, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "UP", Vector3i(0, 1, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "DOWN", Vector3i(0, -1, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "FORWARD", Vector3i(0, 0, -1)); + _VariantCall::add_variant_constant(Variant::VECTOR3I, "BACK", Vector3i(0, 0, 1)); + + _VariantCall::add_constant(Variant::VECTOR2, "AXIS_X", Vector2::AXIS_X); + _VariantCall::add_constant(Variant::VECTOR2, "AXIS_Y", Vector2::AXIS_Y); + + _VariantCall::add_constant(Variant::VECTOR2I, "AXIS_X", Vector2i::AXIS_X); + _VariantCall::add_constant(Variant::VECTOR2I, "AXIS_Y", Vector2i::AXIS_Y); + + _VariantCall::add_variant_constant(Variant::VECTOR2, "ZERO", Vector2(0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR2, "ONE", Vector2(1, 1)); + _VariantCall::add_variant_constant(Variant::VECTOR2, "INF", Vector2(Math_INF, Math_INF)); + _VariantCall::add_variant_constant(Variant::VECTOR2, "LEFT", Vector2(-1, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR2, "RIGHT", Vector2(1, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR2, "UP", Vector2(0, -1)); + _VariantCall::add_variant_constant(Variant::VECTOR2, "DOWN", Vector2(0, 1)); + + _VariantCall::add_variant_constant(Variant::VECTOR2I, "ZERO", Vector2i(0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR2I, "ONE", Vector2i(1, 1)); + _VariantCall::add_variant_constant(Variant::VECTOR2I, "LEFT", Vector2i(-1, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR2I, "RIGHT", Vector2i(1, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR2I, "UP", Vector2i(0, -1)); + _VariantCall::add_variant_constant(Variant::VECTOR2I, "DOWN", Vector2i(0, 1)); + + _VariantCall::add_variant_constant(Variant::TRANSFORM2D, "IDENTITY", Transform2D()); + _VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_X", Transform2D(-1, 0, 0, 1, 0, 0)); + _VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_Y", Transform2D(1, 0, 0, -1, 0, 0)); + + Transform identity_transform = Transform(); + Transform flip_x_transform = Transform(-1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0); + Transform flip_y_transform = Transform(1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0); + Transform flip_z_transform = Transform(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0); + _VariantCall::add_variant_constant(Variant::TRANSFORM, "IDENTITY", identity_transform); + _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_X", flip_x_transform); + _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_Y", flip_y_transform); + _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_Z", flip_z_transform); + + Basis identity_basis = Basis(); + Basis flip_x_basis = Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1); + Basis flip_y_basis = Basis(1, 0, 0, 0, -1, 0, 0, 0, 1); + Basis flip_z_basis = Basis(1, 0, 0, 0, 1, 0, 0, 0, -1); + _VariantCall::add_variant_constant(Variant::BASIS, "IDENTITY", identity_basis); + _VariantCall::add_variant_constant(Variant::BASIS, "FLIP_X", flip_x_basis); + _VariantCall::add_variant_constant(Variant::BASIS, "FLIP_Y", flip_y_basis); + _VariantCall::add_variant_constant(Variant::BASIS, "FLIP_Z", flip_z_basis); + + _VariantCall::add_variant_constant(Variant::PLANE, "PLANE_YZ", Plane(Vector3(1, 0, 0), 0)); + _VariantCall::add_variant_constant(Variant::PLANE, "PLANE_XZ", Plane(Vector3(0, 1, 0), 0)); + _VariantCall::add_variant_constant(Variant::PLANE, "PLANE_XY", Plane(Vector3(0, 0, 1), 0)); + + _VariantCall::add_variant_constant(Variant::QUAT, "IDENTITY", Quat(0, 0, 0, 1)); +} + +void Variant::_register_variant_methods() { + _register_variant_builtin_methods(); //needs to be out due to namespace +} + +void Variant::_unregister_variant_methods() { + //clear methods + memdelete_arr(builtin_method_names); + memdelete_arr(builtin_method_info); + memdelete_arr(_VariantCall::constant_data); +} diff --git a/core/variant/variant_construct.cpp b/core/variant/variant_construct.cpp new file mode 100644 index 0000000000..9835734583 --- /dev/null +++ b/core/variant/variant_construct.cpp @@ -0,0 +1,871 @@ +/*************************************************************************/ +/* variant_construct.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "variant.h" + +#include "core/core_string_names.h" +#include "core/crypto/crypto_core.h" +#include "core/debugger/engine_debugger.h" +#include "core/io/compression.h" +#include "core/object/class_db.h" +#include "core/os/os.h" +#include "core/templates/local_vector.h" +#include "core/templates/oa_hash_map.h" + +template <class T> +struct PtrConstruct {}; + +#define MAKE_PTRCONSTRUCT(m_type) \ + template <> \ + struct PtrConstruct<m_type> { \ + _FORCE_INLINE_ static void construct(const m_type &p_value, void *p_ptr) { \ + memnew_placement(p_ptr, m_type(p_value)); \ + } \ + }; + +MAKE_PTRCONSTRUCT(bool); +MAKE_PTRCONSTRUCT(int64_t); +MAKE_PTRCONSTRUCT(double); +MAKE_PTRCONSTRUCT(String); +MAKE_PTRCONSTRUCT(Vector2); +MAKE_PTRCONSTRUCT(Vector2i); +MAKE_PTRCONSTRUCT(Rect2); +MAKE_PTRCONSTRUCT(Rect2i); +MAKE_PTRCONSTRUCT(Vector3); +MAKE_PTRCONSTRUCT(Vector3i); +MAKE_PTRCONSTRUCT(Transform2D); +MAKE_PTRCONSTRUCT(Plane); +MAKE_PTRCONSTRUCT(Quat); +MAKE_PTRCONSTRUCT(AABB); +MAKE_PTRCONSTRUCT(Basis); +MAKE_PTRCONSTRUCT(Transform); +MAKE_PTRCONSTRUCT(Color); +MAKE_PTRCONSTRUCT(StringName); +MAKE_PTRCONSTRUCT(NodePath); +MAKE_PTRCONSTRUCT(RID); + +template <> +struct PtrConstruct<Object *> { + _FORCE_INLINE_ static void construct(Object *p_value, void *p_ptr) { + *((Object **)p_ptr) = p_value; + } +}; + +MAKE_PTRCONSTRUCT(Callable); +MAKE_PTRCONSTRUCT(Signal); +MAKE_PTRCONSTRUCT(Dictionary); +MAKE_PTRCONSTRUCT(Array); +MAKE_PTRCONSTRUCT(PackedByteArray); +MAKE_PTRCONSTRUCT(PackedInt32Array); +MAKE_PTRCONSTRUCT(PackedInt64Array); +MAKE_PTRCONSTRUCT(PackedFloat32Array); +MAKE_PTRCONSTRUCT(PackedFloat64Array); +MAKE_PTRCONSTRUCT(PackedStringArray); +MAKE_PTRCONSTRUCT(PackedVector2Array); +MAKE_PTRCONSTRUCT(PackedVector3Array); +MAKE_PTRCONSTRUCT(PackedColorArray); +MAKE_PTRCONSTRUCT(Variant); + +template <class T, class... P> +class VariantConstructor { + template <size_t... Is> + static _FORCE_INLINE_ void construct_helper(T &base, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) { + r_error.error = Callable::CallError::CALL_OK; + +#ifdef DEBUG_METHODS_ENABLED + base = T(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...); +#else + base = T(VariantCaster<P>::cast(*p_args[Is])...); +#endif + } + + template <size_t... Is> + static _FORCE_INLINE_ void validated_construct_helper(T &base, const Variant **p_args, IndexSequence<Is...>) { + base = T((*VariantGetInternalPtr<P>::get_ptr(p_args[Is]))...); + } + + template <size_t... Is> + static _FORCE_INLINE_ void ptr_construct_helper(void *base, const void **p_args, IndexSequence<Is...>) { + PtrConstruct<T>::construct(T(PtrToArg<P>::convert(p_args[Is])...), base); + } + +public: + static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { + r_error.error = Callable::CallError::CALL_OK; + VariantTypeChanger<T>::change(&r_ret); + construct_helper(*VariantGetInternalPtr<T>::get_ptr(&r_ret), p_args, r_error, BuildIndexSequence<sizeof...(P)>{}); + } + + static void validated_construct(Variant *r_ret, const Variant **p_args) { + VariantTypeChanger<T>::change(r_ret); + validated_construct_helper(*VariantGetInternalPtr<T>::get_ptr(r_ret), p_args, BuildIndexSequence<sizeof...(P)>{}); + } + static void ptr_construct(void *base, const void **p_args) { + ptr_construct_helper(base, p_args, BuildIndexSequence<sizeof...(P)>{}); + } + + static int get_argument_count() { + return sizeof...(P); + } + + static Variant::Type get_argument_type(int p_arg) { + return call_get_argument_type<P...>(p_arg); + } + + static Variant::Type get_base_type() { + return GetTypeInfo<T>::VARIANT_TYPE; + } +}; + +class VariantConstructorObject { +public: + static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { + VariantInternal::clear(&r_ret); + if (p_args[0]->get_type() == Variant::NIL) { + VariantInternal::object_assign_null(&r_ret); + r_error.error = Callable::CallError::CALL_OK; + } else if (p_args[0]->get_type() == Variant::OBJECT) { + VariantInternal::object_assign(&r_ret, p_args[0]); + r_error.error = Callable::CallError::CALL_OK; + } else { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::OBJECT; + } + } + + static void validated_construct(Variant *r_ret, const Variant **p_args) { + VariantInternal::clear(r_ret); + VariantInternal::object_assign(r_ret, p_args[0]); + } + static void ptr_construct(void *base, const void **p_args) { + PtrConstruct<Object *>::construct(PtrToArg<Object *>::convert(p_args[0]), base); + } + + static int get_argument_count() { + return 1; + } + + static Variant::Type get_argument_type(int p_arg) { + return Variant::OBJECT; + } + + static Variant::Type get_base_type() { + return Variant::OBJECT; + } +}; + +class VariantConstructorNilObject { +public: + static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { + if (p_args[0]->get_type() != Variant::NIL) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::NIL; + } + + VariantInternal::clear(&r_ret); + VariantInternal::object_assign_null(&r_ret); + } + + static void validated_construct(Variant *r_ret, const Variant **p_args) { + VariantInternal::clear(r_ret); + VariantInternal::object_assign_null(r_ret); + } + static void ptr_construct(void *base, const void **p_args) { + PtrConstruct<Object *>::construct(nullptr, base); + } + + static int get_argument_count() { + return 1; + } + + static Variant::Type get_argument_type(int p_arg) { + return Variant::NIL; + } + + static Variant::Type get_base_type() { + return Variant::OBJECT; + } +}; + +class VariantConstructorCallableArgs { +public: + static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { + ObjectID object_id; + StringName method; + + if (p_args[0]->get_type() == Variant::NIL) { + // leave as is + } else if (p_args[0]->get_type() == Variant::OBJECT) { + object_id = VariantInternal::get_object_id(p_args[0]); + } else { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::OBJECT; + return; + } + + if (p_args[1]->get_type() == Variant::STRING_NAME) { + method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]); + } else if (p_args[1]->get_type() == Variant::STRING) { + method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]); + } else { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 1; + r_error.expected = Variant::STRING_NAME; + return; + } + + VariantTypeChanger<Callable>::change(&r_ret); + *VariantGetInternalPtr<Callable>::get_ptr(&r_ret) = Callable(object_id, method); + } + + static void validated_construct(Variant *r_ret, const Variant **p_args) { + VariantTypeChanger<Callable>::change(r_ret); + *VariantGetInternalPtr<Callable>::get_ptr(r_ret) = Callable(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1])); + } + static void ptr_construct(void *base, const void **p_args) { + PtrConstruct<Callable>::construct(Callable(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base); + } + + static int get_argument_count() { + return 2; + } + + static Variant::Type get_argument_type(int p_arg) { + if (p_arg == 0) { + return Variant::OBJECT; + } else { + return Variant::STRING_NAME; + } + } + + static Variant::Type get_base_type() { + return Variant::CALLABLE; + } +}; + +class VariantConstructorSignalArgs { +public: + static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { + ObjectID object_id; + StringName method; + + if (p_args[0]->get_type() == Variant::NIL) { + // leave as is + } else if (p_args[0]->get_type() == Variant::OBJECT) { + object_id = VariantInternal::get_object_id(p_args[0]); + } else { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::OBJECT; + return; + } + + if (p_args[1]->get_type() == Variant::STRING_NAME) { + method = *VariantGetInternalPtr<StringName>::get_ptr(p_args[1]); + } else if (p_args[1]->get_type() == Variant::STRING) { + method = *VariantGetInternalPtr<String>::get_ptr(p_args[1]); + } else { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 1; + r_error.expected = Variant::STRING_NAME; + return; + } + + VariantTypeChanger<Signal>::change(&r_ret); + *VariantGetInternalPtr<Signal>::get_ptr(&r_ret) = Signal(object_id, method); + } + + static void validated_construct(Variant *r_ret, const Variant **p_args) { + VariantTypeChanger<Signal>::change(r_ret); + *VariantGetInternalPtr<Signal>::get_ptr(r_ret) = Signal(VariantInternal::get_object_id(p_args[0]), *VariantGetInternalPtr<StringName>::get_ptr(p_args[1])); + } + static void ptr_construct(void *base, const void **p_args) { + PtrConstruct<Signal>::construct(Signal(PtrToArg<Object *>::convert(p_args[0]), PtrToArg<StringName>::convert(p_args[1])), base); + } + + static int get_argument_count() { + return 2; + } + + static Variant::Type get_argument_type(int p_arg) { + if (p_arg == 0) { + return Variant::OBJECT; + } else { + return Variant::STRING_NAME; + } + } + + static Variant::Type get_base_type() { + return Variant::SIGNAL; + } +}; + +template <class T> +class VariantConstructorToArray { +public: + static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { + if (p_args[0]->get_type() != GetTypeInfo<T>::VARIANT_TYPE) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = GetTypeInfo<T>::VARIANT_TYPE; + return; + } + + VariantTypeChanger<Array>::change(&r_ret); + Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(&r_ret); + const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]); + + int size = src_arr.size(); + dst_arr.resize(size); + for (int i = 0; i < size; i++) { + dst_arr[i] = src_arr[i]; + } + } + + static void validated_construct(Variant *r_ret, const Variant **p_args) { + VariantTypeChanger<Array>::change(r_ret); + Array &dst_arr = *VariantGetInternalPtr<Array>::get_ptr(r_ret); + const T &src_arr = *VariantGetInternalPtr<T>::get_ptr(p_args[0]); + + int size = src_arr.size(); + dst_arr.resize(size); + for (int i = 0; i < size; i++) { + dst_arr[i] = src_arr[i]; + } + } + static void ptr_construct(void *base, const void **p_args) { + Array dst_arr; + T src_arr = PtrToArg<T>::convert(p_args[0]); + + int size = src_arr.size(); + dst_arr.resize(size); + for (int i = 0; i < size; i++) { + dst_arr[i] = src_arr[i]; + } + + PtrConstruct<Array>::construct(dst_arr, base); + } + + static int get_argument_count() { + return 1; + } + + static Variant::Type get_argument_type(int p_arg) { + return GetTypeInfo<T>::VARIANT_TYPE; + } + + static Variant::Type get_base_type() { + return Variant::ARRAY; + } +}; + +template <class T> +class VariantConstructorFromArray { +public: + static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { + if (p_args[0]->get_type() != Variant::ARRAY) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::ARRAY; + return; + } + + VariantTypeChanger<T>::change(&r_ret); + const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]); + T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(&r_ret); + + int size = src_arr.size(); + dst_arr.resize(size); + for (int i = 0; i < size; i++) { + dst_arr.write[i] = src_arr[i]; + } + } + + static void validated_construct(Variant *r_ret, const Variant **p_args) { + VariantTypeChanger<T>::change(r_ret); + const Array &src_arr = *VariantGetInternalPtr<Array>::get_ptr(p_args[0]); + T &dst_arr = *VariantGetInternalPtr<T>::get_ptr(r_ret); + + int size = src_arr.size(); + dst_arr.resize(size); + for (int i = 0; i < size; i++) { + dst_arr.write[i] = src_arr[i]; + } + } + static void ptr_construct(void *base, const void **p_args) { + Array src_arr = PtrToArg<Array>::convert(p_args[0]); + T dst_arr; + + int size = src_arr.size(); + dst_arr.resize(size); + for (int i = 0; i < size; i++) { + dst_arr.write[i] = src_arr[i]; + } + + PtrConstruct<T>::construct(dst_arr, base); + } + + static int get_argument_count() { + return 1; + } + + static Variant::Type get_argument_type(int p_arg) { + return Variant::ARRAY; + } + + static Variant::Type get_base_type() { + return GetTypeInfo<T>::VARIANT_TYPE; + } +}; + +class VariantConstructorNil { +public: + static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { + if (p_args[0]->get_type() != Variant::NIL) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::NIL; + return; + } + + r_error.error = Callable::CallError::CALL_OK; + VariantInternal::clear(&r_ret); + } + + static void validated_construct(Variant *r_ret, const Variant **p_args) { + VariantInternal::clear(r_ret); + } + static void ptr_construct(void *base, const void **p_args) { + PtrConstruct<Variant>::construct(Variant(), base); + } + + static int get_argument_count() { + return 1; + } + + static Variant::Type get_argument_type(int p_arg) { + return Variant::NIL; + } + + static Variant::Type get_base_type() { + return Variant::NIL; + } +}; + +template <class T> +class VariantConstructNoArgs { +public: + static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { + VariantTypeChanger<T>::change_and_reset(&r_ret); + r_error.error = Callable::CallError::CALL_OK; + } + + static void validated_construct(Variant *r_ret, const Variant **p_args) { + VariantTypeChanger<T>::change_and_reset(r_ret); + } + static void ptr_construct(void *base, const void **p_args) { + PtrConstruct<T>::construct(T(), base); + } + + static int get_argument_count() { + return 0; + } + + static Variant::Type get_argument_type(int p_arg) { + return Variant::NIL; + } + + static Variant::Type get_base_type() { + return GetTypeInfo<T>::VARIANT_TYPE; + } +}; + +class VariantConstructNoArgsNil { +public: + static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { + VariantInternal::clear(&r_ret); + r_error.error = Callable::CallError::CALL_OK; + } + + static void validated_construct(Variant *r_ret, const Variant **p_args) { + VariantInternal::clear(r_ret); + } + static void ptr_construct(void *base, const void **p_args) { + ERR_FAIL_MSG("can't ptrcall nil constructor"); + } + + static int get_argument_count() { + return 0; + } + + static Variant::Type get_argument_type(int p_arg) { + return Variant::NIL; + } + + static Variant::Type get_base_type() { + return Variant::NIL; + } +}; + +class VariantConstructNoArgsObject { +public: + static void construct(Variant &r_ret, const Variant **p_args, Callable::CallError &r_error) { + VariantInternal::clear(&r_ret); + VariantInternal::object_assign_null(&r_ret); + r_error.error = Callable::CallError::CALL_OK; + } + + static void validated_construct(Variant *r_ret, const Variant **p_args) { + VariantInternal::clear(r_ret); + VariantInternal::object_assign_null(r_ret); + } + static void ptr_construct(void *base, const void **p_args) { + PtrConstruct<Object *>::construct(nullptr, base); + } + + static int get_argument_count() { + return 0; + } + + static Variant::Type get_argument_type(int p_arg) { + return Variant::NIL; + } + + static Variant::Type get_base_type() { + return Variant::OBJECT; + } +}; + +struct VariantConstructData { + void (*construct)(Variant &r_base, const Variant **p_args, Callable::CallError &r_error); + Variant::ValidatedConstructor validated_construct; + Variant::PTRConstructor ptr_construct; + Variant::Type (*get_argument_type)(int); + int argument_count; + Vector<String> arg_names; +}; + +static LocalVector<VariantConstructData> construct_data[Variant::VARIANT_MAX]; + +template <class T> +static void add_constructor(const Vector<String> &arg_names) { + ERR_FAIL_COND_MSG(arg_names.size() != T::get_argument_count(), "Argument names size mismatch for " + Variant::get_type_name(T::get_base_type()) + "."); + + VariantConstructData cd; + cd.construct = T::construct; + cd.validated_construct = T::validated_construct; + cd.ptr_construct = T::ptr_construct; + cd.get_argument_type = T::get_argument_type; + cd.argument_count = T::get_argument_count(); + cd.arg_names = arg_names; + construct_data[T::get_base_type()].push_back(cd); +} + +void Variant::_register_variant_constructors() { + add_constructor<VariantConstructNoArgsNil>(sarray()); + add_constructor<VariantConstructorNil>(sarray("from")); + + add_constructor<VariantConstructNoArgs<bool>>(sarray()); + add_constructor<VariantConstructor<bool, bool>>(sarray("from")); + add_constructor<VariantConstructor<bool, int64_t>>(sarray("from")); + add_constructor<VariantConstructor<bool, double>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<int64_t>>(sarray()); + add_constructor<VariantConstructor<int64_t, int64_t>>(sarray("from")); + add_constructor<VariantConstructor<int64_t, double>>(sarray("from")); + add_constructor<VariantConstructor<int64_t, bool>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<double>>(sarray()); + add_constructor<VariantConstructor<double, double>>(sarray("from")); + add_constructor<VariantConstructor<double, int64_t>>(sarray("from")); + add_constructor<VariantConstructor<double, bool>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<String>>(sarray()); + add_constructor<VariantConstructor<String, String>>(sarray("from")); + add_constructor<VariantConstructor<String, StringName>>(sarray("from")); + add_constructor<VariantConstructor<String, NodePath>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<Vector2>>(sarray()); + add_constructor<VariantConstructor<Vector2, Vector2>>(sarray("from")); + add_constructor<VariantConstructor<Vector2, Vector2i>>(sarray("from")); + add_constructor<VariantConstructor<Vector2, double, double>>(sarray("x", "y")); + + add_constructor<VariantConstructNoArgs<Vector2i>>(sarray()); + add_constructor<VariantConstructor<Vector2i, Vector2i>>(sarray("from")); + add_constructor<VariantConstructor<Vector2i, Vector2>>(sarray("from")); + add_constructor<VariantConstructor<Vector2i, int64_t, int64_t>>(sarray("x", "y")); + + add_constructor<VariantConstructNoArgs<Rect2>>(sarray()); + add_constructor<VariantConstructor<Rect2, Rect2>>(sarray("from")); + add_constructor<VariantConstructor<Rect2, Rect2i>>(sarray("from")); + add_constructor<VariantConstructor<Rect2, Vector2, Vector2>>(sarray("position", "size")); + add_constructor<VariantConstructor<Rect2, double, double, double, double>>(sarray("x", "y", "width", "height")); + + add_constructor<VariantConstructNoArgs<Rect2i>>(sarray()); + add_constructor<VariantConstructor<Rect2i, Rect2i>>(sarray("from")); + add_constructor<VariantConstructor<Rect2i, Rect2>>(sarray("from")); + add_constructor<VariantConstructor<Rect2i, Vector2i, Vector2i>>(sarray("position", "size")); + add_constructor<VariantConstructor<Rect2i, int64_t, int64_t, int64_t, int64_t>>(sarray("x", "y", "width", "height")); + + add_constructor<VariantConstructNoArgs<Vector3>>(sarray()); + add_constructor<VariantConstructor<Vector3, Vector3>>(sarray("from")); + add_constructor<VariantConstructor<Vector3, Vector3i>>(sarray("from")); + add_constructor<VariantConstructor<Vector3, double, double, double>>(sarray("x", "y", "z")); + + add_constructor<VariantConstructNoArgs<Vector3i>>(sarray()); + add_constructor<VariantConstructor<Vector3i, Vector3i>>(sarray("from")); + add_constructor<VariantConstructor<Vector3i, Vector3>>(sarray("from")); + add_constructor<VariantConstructor<Vector3i, int64_t, int64_t, int64_t>>(sarray("x", "y", "z")); + + add_constructor<VariantConstructNoArgs<Transform2D>>(sarray()); + add_constructor<VariantConstructor<Transform2D, Transform2D>>(sarray("from")); + add_constructor<VariantConstructor<Transform2D, float, Vector2>>(sarray("rotation", "position")); + add_constructor<VariantConstructor<Transform2D, Vector2, Vector2, Vector2>>(sarray("x_axis", "y_axis", "origin")); + + add_constructor<VariantConstructNoArgs<Plane>>(sarray()); + add_constructor<VariantConstructor<Plane, Plane>>(sarray("from")); + add_constructor<VariantConstructor<Plane, Vector3, double>>(sarray("normal", "d")); + add_constructor<VariantConstructor<Plane, Vector3, Vector3>>(sarray("point", "normal")); + add_constructor<VariantConstructor<Plane, Vector3, Vector3, Vector3>>(sarray("point1", "point2", "point3")); + add_constructor<VariantConstructor<Plane, double, double, double, double>>(sarray("a", "b", "c", "d")); + + add_constructor<VariantConstructNoArgs<Quat>>(sarray()); + add_constructor<VariantConstructor<Quat, Quat>>(sarray("from")); + add_constructor<VariantConstructor<Quat, Basis>>(sarray("from")); + add_constructor<VariantConstructor<Quat, Vector3>>(sarray("euler")); + add_constructor<VariantConstructor<Quat, Vector3, double>>(sarray("axis", "angle")); + add_constructor<VariantConstructor<Quat, Vector3, Vector3>>(sarray("arc_from", "arc_to")); + add_constructor<VariantConstructor<Quat, double, double, double, double>>(sarray("x", "y", "z", "w")); + + add_constructor<VariantConstructNoArgs<::AABB>>(sarray()); + add_constructor<VariantConstructor<::AABB, ::AABB>>(sarray("from")); + add_constructor<VariantConstructor<::AABB, Vector3, Vector3>>(sarray("position", "size")); + + add_constructor<VariantConstructNoArgs<Basis>>(sarray()); + add_constructor<VariantConstructor<Basis, Basis>>(sarray("from")); + add_constructor<VariantConstructor<Basis, Quat>>(sarray("from")); + add_constructor<VariantConstructor<Basis, Vector3>>(sarray("euler")); + add_constructor<VariantConstructor<Basis, Vector3, double>>(sarray("axis", "phi")); + add_constructor<VariantConstructor<Basis, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis")); + + add_constructor<VariantConstructNoArgs<Transform>>(sarray()); + add_constructor<VariantConstructor<Transform, Transform>>(sarray("from")); + add_constructor<VariantConstructor<Transform, Basis, Vector3>>(sarray("basis", "origin")); + add_constructor<VariantConstructor<Transform, Vector3, Vector3, Vector3, Vector3>>(sarray("x_axis", "y_axis", "z_axis", "origin")); + + add_constructor<VariantConstructNoArgs<Color>>(sarray()); + add_constructor<VariantConstructor<Color, Color>>(sarray("from")); + add_constructor<VariantConstructor<Color, Color, double>>(sarray("from", "alpha")); + add_constructor<VariantConstructor<Color, double, double, double>>(sarray("r", "g", "b")); + add_constructor<VariantConstructor<Color, double, double, double, double>>(sarray("r", "g", "b", "a")); + + add_constructor<VariantConstructNoArgs<StringName>>(sarray()); + add_constructor<VariantConstructor<StringName, StringName>>(sarray("from")); + add_constructor<VariantConstructor<StringName, String>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<NodePath>>(sarray()); + add_constructor<VariantConstructor<NodePath, NodePath>>(sarray("from")); + add_constructor<VariantConstructor<NodePath, String>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<::RID>>(sarray()); + add_constructor<VariantConstructor<::RID, ::RID>>(sarray("from")); + + add_constructor<VariantConstructNoArgsObject>(sarray()); + add_constructor<VariantConstructorObject>(sarray("from")); + add_constructor<VariantConstructorNilObject>(sarray("from")); + + add_constructor<VariantConstructNoArgs<Callable>>(sarray()); + add_constructor<VariantConstructor<Callable, Callable>>(sarray("from")); + add_constructor<VariantConstructorCallableArgs>(sarray("object", "method")); + + add_constructor<VariantConstructNoArgs<Signal>>(sarray()); + add_constructor<VariantConstructor<Signal, Signal>>(sarray("from")); + add_constructor<VariantConstructorSignalArgs>(sarray("object", "signal")); + + add_constructor<VariantConstructNoArgs<Dictionary>>(sarray()); + add_constructor<VariantConstructor<Dictionary, Dictionary>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<Array>>(sarray()); + add_constructor<VariantConstructor<Array, Array>>(sarray("from")); + add_constructor<VariantConstructorToArray<PackedByteArray>>(sarray("from")); + add_constructor<VariantConstructorToArray<PackedInt32Array>>(sarray("from")); + add_constructor<VariantConstructorToArray<PackedInt64Array>>(sarray("from")); + add_constructor<VariantConstructorToArray<PackedFloat32Array>>(sarray("from")); + add_constructor<VariantConstructorToArray<PackedFloat64Array>>(sarray("from")); + add_constructor<VariantConstructorToArray<PackedStringArray>>(sarray("from")); + add_constructor<VariantConstructorToArray<PackedVector2Array>>(sarray("from")); + add_constructor<VariantConstructorToArray<PackedVector3Array>>(sarray("from")); + add_constructor<VariantConstructorToArray<PackedColorArray>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<PackedByteArray>>(sarray()); + add_constructor<VariantConstructor<PackedByteArray, PackedByteArray>>(sarray("from")); + add_constructor<VariantConstructorFromArray<PackedByteArray>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<PackedInt32Array>>(sarray()); + add_constructor<VariantConstructor<PackedInt32Array, PackedInt32Array>>(sarray("from")); + add_constructor<VariantConstructorFromArray<PackedInt32Array>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<PackedInt64Array>>(sarray()); + add_constructor<VariantConstructor<PackedInt64Array, PackedInt64Array>>(sarray("from")); + add_constructor<VariantConstructorFromArray<PackedInt64Array>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<PackedFloat32Array>>(sarray()); + add_constructor<VariantConstructor<PackedFloat32Array, PackedFloat32Array>>(sarray("from")); + add_constructor<VariantConstructorFromArray<PackedFloat32Array>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<PackedFloat64Array>>(sarray()); + add_constructor<VariantConstructor<PackedFloat64Array, PackedFloat64Array>>(sarray("from")); + add_constructor<VariantConstructorFromArray<PackedFloat64Array>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<PackedStringArray>>(sarray()); + add_constructor<VariantConstructor<PackedStringArray, PackedStringArray>>(sarray("from")); + add_constructor<VariantConstructorFromArray<PackedStringArray>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<PackedVector2Array>>(sarray()); + add_constructor<VariantConstructor<PackedVector2Array, PackedVector2Array>>(sarray("from")); + add_constructor<VariantConstructorFromArray<PackedVector2Array>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<PackedVector3Array>>(sarray()); + add_constructor<VariantConstructor<PackedVector3Array, PackedVector3Array>>(sarray("from")); + add_constructor<VariantConstructorFromArray<PackedVector3Array>>(sarray("from")); + + add_constructor<VariantConstructNoArgs<PackedColorArray>>(sarray()); + add_constructor<VariantConstructor<PackedColorArray, PackedColorArray>>(sarray("from")); + add_constructor<VariantConstructorFromArray<PackedColorArray>>(sarray("from")); +} + +void Variant::_unregister_variant_constructors() { + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + construct_data[i].clear(); + } +} + +void Variant::construct(Variant::Type p_type, Variant &base, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + uint32_t s = construct_data[p_type].size(); + for (uint32_t i = 0; i < s; i++) { + int argc = construct_data[p_type][i].argument_count; + if (argc != p_argcount) { + continue; + } + bool args_match = true; + for (int j = 0; j < argc; j++) { + if (!Variant::can_convert_strict(p_args[j]->get_type(), construct_data[p_type][i].get_argument_type(j))) { + args_match = false; + break; + } + } + + if (!args_match) { + continue; + } + + construct_data[p_type][i].construct(base, p_args, r_error); + return; + } + + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; +} + +int Variant::get_constructor_count(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1); + return construct_data[p_type].size(); +} + +Variant::ValidatedConstructor Variant::get_validated_constructor(Variant::Type p_type, int p_constructor) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), nullptr); + return construct_data[p_type][p_constructor].validated_construct; +} + +Variant::PTRConstructor Variant::get_ptr_constructor(Variant::Type p_type, int p_constructor) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), nullptr); + return construct_data[p_type][p_constructor].ptr_construct; +} + +int Variant::get_constructor_argument_count(Variant::Type p_type, int p_constructor) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1); + ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), -1); + return construct_data[p_type][p_constructor].argument_count; +} + +Variant::Type Variant::get_constructor_argument_type(Variant::Type p_type, int p_constructor, int p_argument) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::VARIANT_MAX); + ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), Variant::VARIANT_MAX); + return construct_data[p_type][p_constructor].get_argument_type(p_argument); +} + +String Variant::get_constructor_argument_name(Variant::Type p_type, int p_constructor, int p_argument) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, String()); + ERR_FAIL_INDEX_V(p_constructor, (int)construct_data[p_type].size(), String()); + return construct_data[p_type][p_constructor].arg_names[p_argument]; +} + +void VariantInternal::object_assign(Variant *v, const Object *o) { + if (o) { + if (o->is_reference()) { + Reference *reference = const_cast<Reference *>(static_cast<const Reference *>(o)); + if (!reference->init_ref()) { + v->_get_obj().obj = nullptr; + v->_get_obj().id = ObjectID(); + return; + } + } + + v->_get_obj().obj = const_cast<Object *>(o); + v->_get_obj().id = o->get_instance_id(); + } else { + v->_get_obj().obj = nullptr; + v->_get_obj().id = ObjectID(); + } +} + +void Variant::get_constructor_list(Type p_type, List<MethodInfo> *r_list) { + ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX); + + MethodInfo mi; + mi.return_val.type = p_type; + mi.name = get_type_name(p_type); + + for (int i = 0; i < get_constructor_count(p_type); i++) { + int ac = get_constructor_argument_count(p_type, i); + mi.arguments.clear(); + for (int j = 0; j < ac; j++) { + PropertyInfo arg; + arg.name = get_constructor_argument_name(p_type, i, j); + arg.type = get_constructor_argument_type(p_type, i, j); + mi.arguments.push_back(arg); + } + r_list->push_back(mi); + } +} diff --git a/core/variant/variant_internal.h b/core/variant/variant_internal.h new file mode 100644 index 0000000000..7d33d85cd6 --- /dev/null +++ b/core/variant/variant_internal.h @@ -0,0 +1,1381 @@ +/*************************************************************************/ +/* variant_internal.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VARIANT_INTERNAL_H +#define VARIANT_INTERNAL_H + +#include "variant.h" + +// For use when you want to access the internal pointer of a Variant directly. +// Use with caution. You need to be sure that the type is correct. +class VariantInternal { +public: + // Set type. + _FORCE_INLINE_ static void initialize(Variant *v, Variant::Type p_type) { + v->clear(); + v->type = p_type; + + switch (p_type) { + case Variant::AABB: + init_aabb(v); + break; + case Variant::TRANSFORM2D: + init_transform2d(v); + break; + case Variant::TRANSFORM: + init_transform(v); + break; + case Variant::STRING: + init_string(v); + break; + case Variant::STRING_NAME: + init_string_name(v); + break; + case Variant::NODE_PATH: + init_node_path(v); + break; + case Variant::CALLABLE: + init_callable(v); + break; + case Variant::SIGNAL: + init_signal(v); + break; + case Variant::DICTIONARY: + init_dictionary(v); + break; + case Variant::ARRAY: + init_array(v); + break; + case Variant::PACKED_BYTE_ARRAY: + init_byte_array(v); + break; + case Variant::PACKED_INT32_ARRAY: + init_int32_array(v); + break; + case Variant::PACKED_INT64_ARRAY: + init_int64_array(v); + break; + case Variant::PACKED_FLOAT32_ARRAY: + init_float32_array(v); + break; + case Variant::PACKED_FLOAT64_ARRAY: + init_float64_array(v); + break; + case Variant::PACKED_STRING_ARRAY: + init_string_array(v); + break; + case Variant::PACKED_VECTOR2_ARRAY: + init_vector2_array(v); + break; + case Variant::PACKED_VECTOR3_ARRAY: + init_vector3_array(v); + break; + case Variant::PACKED_COLOR_ARRAY: + init_color_array(v); + break; + case Variant::OBJECT: + object_assign_null(v); + break; + default: + break; + } + } + + // Atomic types. + _FORCE_INLINE_ static bool *get_bool(Variant *v) { return &v->_data._bool; } + _FORCE_INLINE_ static const bool *get_bool(const Variant *v) { return &v->_data._bool; } + _FORCE_INLINE_ static int64_t *get_int(Variant *v) { return &v->_data._int; } + _FORCE_INLINE_ static const int64_t *get_int(const Variant *v) { return &v->_data._int; } + _FORCE_INLINE_ static double *get_float(Variant *v) { return &v->_data._float; } + _FORCE_INLINE_ static const double *get_float(const Variant *v) { return &v->_data._float; } + _FORCE_INLINE_ static String *get_string(Variant *v) { return reinterpret_cast<String *>(v->_data._mem); } + _FORCE_INLINE_ static const String *get_string(const Variant *v) { return reinterpret_cast<const String *>(v->_data._mem); } + + // Math types. + _FORCE_INLINE_ static Vector2 *get_vector2(Variant *v) { return reinterpret_cast<Vector2 *>(v->_data._mem); } + _FORCE_INLINE_ static const Vector2 *get_vector2(const Variant *v) { return reinterpret_cast<const Vector2 *>(v->_data._mem); } + _FORCE_INLINE_ static Vector2i *get_vector2i(Variant *v) { return reinterpret_cast<Vector2i *>(v->_data._mem); } + _FORCE_INLINE_ static const Vector2i *get_vector2i(const Variant *v) { return reinterpret_cast<const Vector2i *>(v->_data._mem); } + _FORCE_INLINE_ static Rect2 *get_rect2(Variant *v) { return reinterpret_cast<Rect2 *>(v->_data._mem); } + _FORCE_INLINE_ static const Rect2 *get_rect2(const Variant *v) { return reinterpret_cast<const Rect2 *>(v->_data._mem); } + _FORCE_INLINE_ static Rect2i *get_rect2i(Variant *v) { return reinterpret_cast<Rect2i *>(v->_data._mem); } + _FORCE_INLINE_ static const Rect2i *get_rect2i(const Variant *v) { return reinterpret_cast<const Rect2i *>(v->_data._mem); } + _FORCE_INLINE_ static Vector3 *get_vector3(Variant *v) { return reinterpret_cast<Vector3 *>(v->_data._mem); } + _FORCE_INLINE_ static const Vector3 *get_vector3(const Variant *v) { return reinterpret_cast<const Vector3 *>(v->_data._mem); } + _FORCE_INLINE_ static Vector3i *get_vector3i(Variant *v) { return reinterpret_cast<Vector3i *>(v->_data._mem); } + _FORCE_INLINE_ static const Vector3i *get_vector3i(const Variant *v) { return reinterpret_cast<const Vector3i *>(v->_data._mem); } + _FORCE_INLINE_ static Transform2D *get_transform2d(Variant *v) { return v->_data._transform2d; } + _FORCE_INLINE_ static const Transform2D *get_transform2d(const Variant *v) { return v->_data._transform2d; } + _FORCE_INLINE_ static Plane *get_plane(Variant *v) { return reinterpret_cast<Plane *>(v->_data._mem); } + _FORCE_INLINE_ static const Plane *get_plane(const Variant *v) { return reinterpret_cast<const Plane *>(v->_data._mem); } + _FORCE_INLINE_ static Quat *get_quat(Variant *v) { return reinterpret_cast<Quat *>(v->_data._mem); } + _FORCE_INLINE_ static const Quat *get_quat(const Variant *v) { return reinterpret_cast<const Quat *>(v->_data._mem); } + _FORCE_INLINE_ static ::AABB *get_aabb(Variant *v) { return v->_data._aabb; } + _FORCE_INLINE_ static const ::AABB *get_aabb(const Variant *v) { return v->_data._aabb; } + _FORCE_INLINE_ static Basis *get_basis(Variant *v) { return v->_data._basis; } + _FORCE_INLINE_ static const Basis *get_basis(const Variant *v) { return v->_data._basis; } + _FORCE_INLINE_ static Transform *get_transform(Variant *v) { return v->_data._transform; } + _FORCE_INLINE_ static const Transform *get_transform(const Variant *v) { return v->_data._transform; } + + // Misc types. + _FORCE_INLINE_ static Color *get_color(Variant *v) { return reinterpret_cast<Color *>(v->_data._mem); } + _FORCE_INLINE_ static const Color *get_color(const Variant *v) { return reinterpret_cast<const Color *>(v->_data._mem); } + _FORCE_INLINE_ static StringName *get_string_name(Variant *v) { return reinterpret_cast<StringName *>(v->_data._mem); } + _FORCE_INLINE_ static const StringName *get_string_name(const Variant *v) { return reinterpret_cast<const StringName *>(v->_data._mem); } + _FORCE_INLINE_ static NodePath *get_node_path(Variant *v) { return reinterpret_cast<NodePath *>(v->_data._mem); } + _FORCE_INLINE_ static const NodePath *get_node_path(const Variant *v) { return reinterpret_cast<const NodePath *>(v->_data._mem); } + _FORCE_INLINE_ static ::RID *get_rid(Variant *v) { return reinterpret_cast<::RID *>(v->_data._mem); } + _FORCE_INLINE_ static const ::RID *get_rid(const Variant *v) { return reinterpret_cast<const ::RID *>(v->_data._mem); } + _FORCE_INLINE_ static Callable *get_callable(Variant *v) { return reinterpret_cast<Callable *>(v->_data._mem); } + _FORCE_INLINE_ static const Callable *get_callable(const Variant *v) { return reinterpret_cast<const Callable *>(v->_data._mem); } + _FORCE_INLINE_ static Signal *get_signal(Variant *v) { return reinterpret_cast<Signal *>(v->_data._mem); } + _FORCE_INLINE_ static const Signal *get_signal(const Variant *v) { return reinterpret_cast<const Signal *>(v->_data._mem); } + _FORCE_INLINE_ static Dictionary *get_dictionary(Variant *v) { return reinterpret_cast<Dictionary *>(v->_data._mem); } + _FORCE_INLINE_ static const Dictionary *get_dictionary(const Variant *v) { return reinterpret_cast<const Dictionary *>(v->_data._mem); } + _FORCE_INLINE_ static Array *get_array(Variant *v) { return reinterpret_cast<Array *>(v->_data._mem); } + _FORCE_INLINE_ static const Array *get_array(const Variant *v) { return reinterpret_cast<const Array *>(v->_data._mem); } + + // Typed arrays. + _FORCE_INLINE_ static PackedByteArray *get_byte_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<uint8_t> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static const PackedByteArray *get_byte_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<uint8_t> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static PackedInt32Array *get_int32_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<int32_t> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static const PackedInt32Array *get_int32_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<int32_t> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static PackedInt64Array *get_int64_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<int64_t> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static const PackedInt64Array *get_int64_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<int64_t> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static PackedFloat32Array *get_float32_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<float> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static const PackedFloat32Array *get_float32_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<float> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static PackedFloat64Array *get_float64_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<double> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static const PackedFloat64Array *get_float64_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<double> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static PackedStringArray *get_string_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<String> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static const PackedStringArray *get_string_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<String> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static PackedVector2Array *get_vector2_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<Vector2> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static const PackedVector2Array *get_vector2_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<Vector2> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static PackedVector3Array *get_vector3_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<Vector3> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static const PackedVector3Array *get_vector3_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<Vector3> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static PackedColorArray *get_color_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<Color> *>(v->_data.packed_array)->array; } + _FORCE_INLINE_ static const PackedColorArray *get_color_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<Color> *>(v->_data.packed_array)->array; } + + _FORCE_INLINE_ static Object **get_object(Variant *v) { return (Object **)&v->_get_obj().obj; } + _FORCE_INLINE_ static const Object **get_object(const Variant *v) { return (const Object **)&v->_get_obj().obj; } + + _FORCE_INLINE_ static const ObjectID get_object_id(const Variant *v) { return v->_get_obj().id; } + + template <class T> + _FORCE_INLINE_ static void init_generic(Variant *v) { + v->type = GetTypeInfo<T>::VARIANT_TYPE; + } + + _FORCE_INLINE_ static void init_string(Variant *v) { + memnew_placement(v->_data._mem, String); + v->type = Variant::STRING; + } + + _FORCE_INLINE_ static void init_transform2d(Variant *v) { + v->_data._transform2d = memnew(Transform2D); + v->type = Variant::TRANSFORM2D; + } + _FORCE_INLINE_ static void init_aabb(Variant *v) { + v->_data._aabb = memnew(AABB); + v->type = Variant::AABB; + } + _FORCE_INLINE_ static void init_basis(Variant *v) { + v->_data._basis = memnew(Basis); + v->type = Variant::BASIS; + } + _FORCE_INLINE_ static void init_transform(Variant *v) { + v->_data._transform = memnew(Transform); + v->type = Variant::TRANSFORM; + } + _FORCE_INLINE_ static void init_string_name(Variant *v) { + memnew_placement(v->_data._mem, StringName); + v->type = Variant::STRING_NAME; + } + _FORCE_INLINE_ static void init_node_path(Variant *v) { + memnew_placement(v->_data._mem, NodePath); + v->type = Variant::NODE_PATH; + } + _FORCE_INLINE_ static void init_callable(Variant *v) { + memnew_placement(v->_data._mem, Callable); + v->type = Variant::CALLABLE; + } + _FORCE_INLINE_ static void init_signal(Variant *v) { + memnew_placement(v->_data._mem, Signal); + v->type = Variant::SIGNAL; + } + _FORCE_INLINE_ static void init_dictionary(Variant *v) { + memnew_placement(v->_data._mem, Dictionary); + v->type = Variant::DICTIONARY; + } + _FORCE_INLINE_ static void init_array(Variant *v) { + memnew_placement(v->_data._mem, Array); + v->type = Variant::ARRAY; + } + _FORCE_INLINE_ static void init_byte_array(Variant *v) { + v->_data.packed_array = Variant::PackedArrayRef<uint8_t>::create(Vector<uint8_t>()); + v->type = Variant::PACKED_BYTE_ARRAY; + } + _FORCE_INLINE_ static void init_int32_array(Variant *v) { + v->_data.packed_array = Variant::PackedArrayRef<int32_t>::create(Vector<int32_t>()); + v->type = Variant::PACKED_INT32_ARRAY; + } + _FORCE_INLINE_ static void init_int64_array(Variant *v) { + v->_data.packed_array = Variant::PackedArrayRef<int64_t>::create(Vector<int64_t>()); + v->type = Variant::PACKED_INT64_ARRAY; + } + _FORCE_INLINE_ static void init_float32_array(Variant *v) { + v->_data.packed_array = Variant::PackedArrayRef<float>::create(Vector<float>()); + v->type = Variant::PACKED_FLOAT32_ARRAY; + } + _FORCE_INLINE_ static void init_float64_array(Variant *v) { + v->_data.packed_array = Variant::PackedArrayRef<double>::create(Vector<double>()); + v->type = Variant::PACKED_FLOAT64_ARRAY; + } + _FORCE_INLINE_ static void init_string_array(Variant *v) { + v->_data.packed_array = Variant::PackedArrayRef<String>::create(Vector<String>()); + v->type = Variant::PACKED_STRING_ARRAY; + } + _FORCE_INLINE_ static void init_vector2_array(Variant *v) { + v->_data.packed_array = Variant::PackedArrayRef<Vector2>::create(Vector<Vector2>()); + v->type = Variant::PACKED_VECTOR2_ARRAY; + } + _FORCE_INLINE_ static void init_vector3_array(Variant *v) { + v->_data.packed_array = Variant::PackedArrayRef<Vector3>::create(Vector<Vector3>()); + v->type = Variant::PACKED_VECTOR3_ARRAY; + } + _FORCE_INLINE_ static void init_color_array(Variant *v) { + v->_data.packed_array = Variant::PackedArrayRef<Color>::create(Vector<Color>()); + v->type = Variant::PACKED_COLOR_ARRAY; + } + + _FORCE_INLINE_ static void clear(Variant *v) { + v->clear(); + } + + static void object_assign(Variant *v, const Object *o); // Needs Reference, so it's implemented elsewhere. + + _FORCE_INLINE_ static void object_assign(Variant *v, const Variant *o) { + object_assign(v, o->_get_obj().obj); + } + + _FORCE_INLINE_ static void object_assign_null(Variant *v) { + v->_get_obj().obj = nullptr; + v->_get_obj().id = ObjectID(); + } + + _FORCE_INLINE_ static void *get_opaque_pointer(Variant *v) { + switch (v->type) { + case Variant::NIL: + return nullptr; + case Variant::BOOL: + return get_bool(v); + case Variant::INT: + return get_int(v); + case Variant::FLOAT: + return get_float(v); + case Variant::STRING: + return get_string(v); + case Variant::VECTOR2: + return get_vector2(v); + case Variant::VECTOR2I: + return get_vector2i(v); + case Variant::VECTOR3: + return get_vector3(v); + case Variant::VECTOR3I: + return get_vector3i(v); + case Variant::RECT2: + return get_rect2(v); + case Variant::RECT2I: + return get_rect2i(v); + case Variant::TRANSFORM: + return get_transform(v); + case Variant::TRANSFORM2D: + return get_transform2d(v); + case Variant::QUAT: + return get_quat(v); + case Variant::PLANE: + return get_plane(v); + case Variant::BASIS: + return get_basis(v); + case Variant::AABB: + return get_aabb(v); + case Variant::COLOR: + return get_color(v); + case Variant::STRING_NAME: + return get_string_name(v); + case Variant::NODE_PATH: + return get_node_path(v); + case Variant::RID: + return get_rid(v); + case Variant::CALLABLE: + return get_callable(v); + case Variant::SIGNAL: + return get_signal(v); + case Variant::DICTIONARY: + return get_dictionary(v); + case Variant::ARRAY: + return get_array(v); + case Variant::PACKED_BYTE_ARRAY: + return get_byte_array(v); + case Variant::PACKED_INT32_ARRAY: + return get_int32_array(v); + case Variant::PACKED_INT64_ARRAY: + return get_int64_array(v); + case Variant::PACKED_FLOAT32_ARRAY: + return get_float32_array(v); + case Variant::PACKED_FLOAT64_ARRAY: + return get_float64_array(v); + case Variant::PACKED_STRING_ARRAY: + return get_string_array(v); + case Variant::PACKED_VECTOR2_ARRAY: + return get_vector2_array(v); + case Variant::PACKED_VECTOR3_ARRAY: + return get_vector3_array(v); + case Variant::PACKED_COLOR_ARRAY: + return get_color_array(v); + case Variant::OBJECT: + return v->_get_obj().obj; + case Variant::VARIANT_MAX: + ERR_FAIL_V(nullptr); + } + ERR_FAIL_V(nullptr); + } + + _FORCE_INLINE_ static const void *get_opaque_pointer(const Variant *v) { + switch (v->type) { + case Variant::NIL: + return nullptr; + case Variant::BOOL: + return get_bool(v); + case Variant::INT: + return get_int(v); + case Variant::FLOAT: + return get_float(v); + case Variant::STRING: + return get_string(v); + case Variant::VECTOR2: + return get_vector2(v); + case Variant::VECTOR2I: + return get_vector2i(v); + case Variant::VECTOR3: + return get_vector3(v); + case Variant::VECTOR3I: + return get_vector3i(v); + case Variant::RECT2: + return get_rect2(v); + case Variant::RECT2I: + return get_rect2i(v); + case Variant::TRANSFORM: + return get_transform(v); + case Variant::TRANSFORM2D: + return get_transform2d(v); + case Variant::QUAT: + return get_quat(v); + case Variant::PLANE: + return get_plane(v); + case Variant::BASIS: + return get_basis(v); + case Variant::AABB: + return get_aabb(v); + case Variant::COLOR: + return get_color(v); + case Variant::STRING_NAME: + return get_string_name(v); + case Variant::NODE_PATH: + return get_node_path(v); + case Variant::RID: + return get_rid(v); + case Variant::CALLABLE: + return get_callable(v); + case Variant::SIGNAL: + return get_signal(v); + case Variant::DICTIONARY: + return get_dictionary(v); + case Variant::ARRAY: + return get_array(v); + case Variant::PACKED_BYTE_ARRAY: + return get_byte_array(v); + case Variant::PACKED_INT32_ARRAY: + return get_int32_array(v); + case Variant::PACKED_INT64_ARRAY: + return get_int64_array(v); + case Variant::PACKED_FLOAT32_ARRAY: + return get_float32_array(v); + case Variant::PACKED_FLOAT64_ARRAY: + return get_float64_array(v); + case Variant::PACKED_STRING_ARRAY: + return get_string_array(v); + case Variant::PACKED_VECTOR2_ARRAY: + return get_vector2_array(v); + case Variant::PACKED_VECTOR3_ARRAY: + return get_vector3_array(v); + case Variant::PACKED_COLOR_ARRAY: + return get_color_array(v); + case Variant::OBJECT: + return v->_get_obj().obj; + case Variant::VARIANT_MAX: + ERR_FAIL_V(nullptr); + } + ERR_FAIL_V(nullptr); + } +}; + +template <class T> +struct VariantGetInternalPtr { +}; + +template <> +struct VariantGetInternalPtr<bool> { + static bool *get_ptr(Variant *v) { return VariantInternal::get_bool(v); } + static const bool *get_ptr(const Variant *v) { return VariantInternal::get_bool(v); } +}; + +template <> +struct VariantGetInternalPtr<int8_t> { + static int64_t *get_ptr(Variant *v) { return VariantInternal::get_int(v); } + static const int64_t *get_ptr(const Variant *v) { return VariantInternal::get_int(v); } +}; + +template <> +struct VariantGetInternalPtr<uint8_t> { + static int64_t *get_ptr(Variant *v) { return VariantInternal::get_int(v); } + static const int64_t *get_ptr(const Variant *v) { return VariantInternal::get_int(v); } +}; + +template <> +struct VariantGetInternalPtr<int16_t> { + static int64_t *get_ptr(Variant *v) { return VariantInternal::get_int(v); } + static const int64_t *get_ptr(const Variant *v) { return VariantInternal::get_int(v); } +}; + +template <> +struct VariantGetInternalPtr<uint16_t> { + static int64_t *get_ptr(Variant *v) { return VariantInternal::get_int(v); } + static const int64_t *get_ptr(const Variant *v) { return VariantInternal::get_int(v); } +}; + +template <> +struct VariantGetInternalPtr<int32_t> { + static int64_t *get_ptr(Variant *v) { return VariantInternal::get_int(v); } + static const int64_t *get_ptr(const Variant *v) { return VariantInternal::get_int(v); } +}; + +template <> +struct VariantGetInternalPtr<uint32_t> { + static int64_t *get_ptr(Variant *v) { return VariantInternal::get_int(v); } + static const int64_t *get_ptr(const Variant *v) { return VariantInternal::get_int(v); } +}; + +template <> +struct VariantGetInternalPtr<int64_t> { + static int64_t *get_ptr(Variant *v) { return VariantInternal::get_int(v); } + static const int64_t *get_ptr(const Variant *v) { return VariantInternal::get_int(v); } +}; + +template <> +struct VariantGetInternalPtr<uint64_t> { + static int64_t *get_ptr(Variant *v) { return VariantInternal::get_int(v); } + static const int64_t *get_ptr(const Variant *v) { return VariantInternal::get_int(v); } +}; + +template <> +struct VariantGetInternalPtr<char32_t> { + static int64_t *get_ptr(Variant *v) { return VariantInternal::get_int(v); } + static const int64_t *get_ptr(const Variant *v) { return VariantInternal::get_int(v); } +}; + +template <> +struct VariantGetInternalPtr<ObjectID> { + static int64_t *get_ptr(Variant *v) { return VariantInternal::get_int(v); } + static const int64_t *get_ptr(const Variant *v) { return VariantInternal::get_int(v); } +}; + +template <> +struct VariantGetInternalPtr<Error> { + static int64_t *get_ptr(Variant *v) { return VariantInternal::get_int(v); } + static const int64_t *get_ptr(const Variant *v) { return VariantInternal::get_int(v); } +}; + +template <> +struct VariantGetInternalPtr<float> { + static double *get_ptr(Variant *v) { return VariantInternal::get_float(v); } + static const double *get_ptr(const Variant *v) { return VariantInternal::get_float(v); } +}; + +template <> +struct VariantGetInternalPtr<double> { + static double *get_ptr(Variant *v) { return VariantInternal::get_float(v); } + static const double *get_ptr(const Variant *v) { return VariantInternal::get_float(v); } +}; + +template <> +struct VariantGetInternalPtr<String> { + static String *get_ptr(Variant *v) { return VariantInternal::get_string(v); } + static const String *get_ptr(const Variant *v) { return VariantInternal::get_string(v); } +}; + +template <> +struct VariantGetInternalPtr<Vector2> { + static Vector2 *get_ptr(Variant *v) { return VariantInternal::get_vector2(v); } + static const Vector2 *get_ptr(const Variant *v) { return VariantInternal::get_vector2(v); } +}; + +template <> +struct VariantGetInternalPtr<Vector2i> { + static Vector2i *get_ptr(Variant *v) { return VariantInternal::get_vector2i(v); } + static const Vector2i *get_ptr(const Variant *v) { return VariantInternal::get_vector2i(v); } +}; + +template <> +struct VariantGetInternalPtr<Rect2> { + static Rect2 *get_ptr(Variant *v) { return VariantInternal::get_rect2(v); } + static const Rect2 *get_ptr(const Variant *v) { return VariantInternal::get_rect2(v); } +}; + +template <> +struct VariantGetInternalPtr<Rect2i> { + static Rect2i *get_ptr(Variant *v) { return VariantInternal::get_rect2i(v); } + static const Rect2i *get_ptr(const Variant *v) { return VariantInternal::get_rect2i(v); } +}; + +template <> +struct VariantGetInternalPtr<Vector3> { + static Vector3 *get_ptr(Variant *v) { return VariantInternal::get_vector3(v); } + static const Vector3 *get_ptr(const Variant *v) { return VariantInternal::get_vector3(v); } +}; + +template <> +struct VariantGetInternalPtr<Vector3i> { + static Vector3i *get_ptr(Variant *v) { return VariantInternal::get_vector3i(v); } + static const Vector3i *get_ptr(const Variant *v) { return VariantInternal::get_vector3i(v); } +}; + +template <> +struct VariantGetInternalPtr<Transform2D> { + static Transform2D *get_ptr(Variant *v) { return VariantInternal::get_transform2d(v); } + static const Transform2D *get_ptr(const Variant *v) { return VariantInternal::get_transform2d(v); } +}; + +template <> +struct VariantGetInternalPtr<Transform> { + static Transform *get_ptr(Variant *v) { return VariantInternal::get_transform(v); } + static const Transform *get_ptr(const Variant *v) { return VariantInternal::get_transform(v); } +}; + +template <> +struct VariantGetInternalPtr<Plane> { + static Plane *get_ptr(Variant *v) { return VariantInternal::get_plane(v); } + static const Plane *get_ptr(const Variant *v) { return VariantInternal::get_plane(v); } +}; + +template <> +struct VariantGetInternalPtr<Quat> { + static Quat *get_ptr(Variant *v) { return VariantInternal::get_quat(v); } + static const Quat *get_ptr(const Variant *v) { return VariantInternal::get_quat(v); } +}; + +template <> +struct VariantGetInternalPtr<::AABB> { + static ::AABB *get_ptr(Variant *v) { return VariantInternal::get_aabb(v); } + static const ::AABB *get_ptr(const Variant *v) { return VariantInternal::get_aabb(v); } +}; + +template <> +struct VariantGetInternalPtr<Basis> { + static Basis *get_ptr(Variant *v) { return VariantInternal::get_basis(v); } + static const Basis *get_ptr(const Variant *v) { return VariantInternal::get_basis(v); } +}; + +// + +template <> +struct VariantGetInternalPtr<Color> { + static Color *get_ptr(Variant *v) { return VariantInternal::get_color(v); } + static const Color *get_ptr(const Variant *v) { return VariantInternal::get_color(v); } +}; + +template <> +struct VariantGetInternalPtr<StringName> { + static StringName *get_ptr(Variant *v) { return VariantInternal::get_string_name(v); } + static const StringName *get_ptr(const Variant *v) { return VariantInternal::get_string_name(v); } +}; + +template <> +struct VariantGetInternalPtr<NodePath> { + static NodePath *get_ptr(Variant *v) { return VariantInternal::get_node_path(v); } + static const NodePath *get_ptr(const Variant *v) { return VariantInternal::get_node_path(v); } +}; + +template <> +struct VariantGetInternalPtr<::RID> { + static ::RID *get_ptr(Variant *v) { return VariantInternal::get_rid(v); } + static const ::RID *get_ptr(const Variant *v) { return VariantInternal::get_rid(v); } +}; + +template <> +struct VariantGetInternalPtr<Callable> { + static Callable *get_ptr(Variant *v) { return VariantInternal::get_callable(v); } + static const Callable *get_ptr(const Variant *v) { return VariantInternal::get_callable(v); } +}; + +template <> +struct VariantGetInternalPtr<Signal> { + static Signal *get_ptr(Variant *v) { return VariantInternal::get_signal(v); } + static const Signal *get_ptr(const Variant *v) { return VariantInternal::get_signal(v); } +}; + +template <> +struct VariantGetInternalPtr<Dictionary> { + static Dictionary *get_ptr(Variant *v) { return VariantInternal::get_dictionary(v); } + static const Dictionary *get_ptr(const Variant *v) { return VariantInternal::get_dictionary(v); } +}; + +template <> +struct VariantGetInternalPtr<Array> { + static Array *get_ptr(Variant *v) { return VariantInternal::get_array(v); } + static const Array *get_ptr(const Variant *v) { return VariantInternal::get_array(v); } +}; + +template <> +struct VariantGetInternalPtr<PackedByteArray> { + static PackedByteArray *get_ptr(Variant *v) { return VariantInternal::get_byte_array(v); } + static const PackedByteArray *get_ptr(const Variant *v) { return VariantInternal::get_byte_array(v); } +}; + +template <> +struct VariantGetInternalPtr<PackedInt32Array> { + static PackedInt32Array *get_ptr(Variant *v) { return VariantInternal::get_int32_array(v); } + static const PackedInt32Array *get_ptr(const Variant *v) { return VariantInternal::get_int32_array(v); } +}; + +template <> +struct VariantGetInternalPtr<PackedInt64Array> { + static PackedInt64Array *get_ptr(Variant *v) { return VariantInternal::get_int64_array(v); } + static const PackedInt64Array *get_ptr(const Variant *v) { return VariantInternal::get_int64_array(v); } +}; + +template <> +struct VariantGetInternalPtr<PackedFloat32Array> { + static PackedFloat32Array *get_ptr(Variant *v) { return VariantInternal::get_float32_array(v); } + static const PackedFloat32Array *get_ptr(const Variant *v) { return VariantInternal::get_float32_array(v); } +}; + +template <> +struct VariantGetInternalPtr<PackedFloat64Array> { + static PackedFloat64Array *get_ptr(Variant *v) { return VariantInternal::get_float64_array(v); } + static const PackedFloat64Array *get_ptr(const Variant *v) { return VariantInternal::get_float64_array(v); } +}; + +template <> +struct VariantGetInternalPtr<PackedStringArray> { + static PackedStringArray *get_ptr(Variant *v) { return VariantInternal::get_string_array(v); } + static const PackedStringArray *get_ptr(const Variant *v) { return VariantInternal::get_string_array(v); } +}; + +template <> +struct VariantGetInternalPtr<PackedVector2Array> { + static PackedVector2Array *get_ptr(Variant *v) { return VariantInternal::get_vector2_array(v); } + static const PackedVector2Array *get_ptr(const Variant *v) { return VariantInternal::get_vector2_array(v); } +}; + +template <> +struct VariantGetInternalPtr<PackedVector3Array> { + static PackedVector3Array *get_ptr(Variant *v) { return VariantInternal::get_vector3_array(v); } + static const PackedVector3Array *get_ptr(const Variant *v) { return VariantInternal::get_vector3_array(v); } +}; + +template <> +struct VariantGetInternalPtr<PackedColorArray> { + static PackedColorArray *get_ptr(Variant *v) { return VariantInternal::get_color_array(v); } + static const PackedColorArray *get_ptr(const Variant *v) { return VariantInternal::get_color_array(v); } +}; + +template <class T> +struct VariantInternalAccessor { +}; + +template <> +struct VariantInternalAccessor<bool> { + static _FORCE_INLINE_ bool get(const Variant *v) { return *VariantInternal::get_bool(v); } + static _FORCE_INLINE_ void set(Variant *v, bool p_value) { *VariantInternal::get_bool(v) = p_value; } +}; + +#define VARIANT_ACCESSOR_NUMBER(m_type) \ + template <> \ + struct VariantInternalAccessor<m_type> { \ + static _FORCE_INLINE_ m_type get(const Variant *v) { return (m_type)*VariantInternal::get_int(v); } \ + static _FORCE_INLINE_ void set(Variant *v, m_type p_value) { *VariantInternal::get_int(v) = p_value; } \ + }; + +VARIANT_ACCESSOR_NUMBER(int8_t) +VARIANT_ACCESSOR_NUMBER(uint8_t) +VARIANT_ACCESSOR_NUMBER(int16_t) +VARIANT_ACCESSOR_NUMBER(uint16_t) +VARIANT_ACCESSOR_NUMBER(int32_t) +VARIANT_ACCESSOR_NUMBER(uint32_t) +VARIANT_ACCESSOR_NUMBER(int64_t) +VARIANT_ACCESSOR_NUMBER(uint64_t) +VARIANT_ACCESSOR_NUMBER(char32_t) +VARIANT_ACCESSOR_NUMBER(Error) +VARIANT_ACCESSOR_NUMBER(Side) + +template <> +struct VariantInternalAccessor<ObjectID> { + static _FORCE_INLINE_ ObjectID get(const Variant *v) { return ObjectID(*VariantInternal::get_int(v)); } + static _FORCE_INLINE_ void set(Variant *v, ObjectID p_value) { *VariantInternal::get_int(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<float> { + static _FORCE_INLINE_ float get(const Variant *v) { return *VariantInternal::get_float(v); } + static _FORCE_INLINE_ void set(Variant *v, float p_value) { *VariantInternal::get_float(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<double> { + static _FORCE_INLINE_ double get(const Variant *v) { return *VariantInternal::get_float(v); } + static _FORCE_INLINE_ void set(Variant *v, double p_value) { *VariantInternal::get_float(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<String> { + static _FORCE_INLINE_ const String &get(const Variant *v) { return *VariantInternal::get_string(v); } + static _FORCE_INLINE_ void set(Variant *v, const String &p_value) { *VariantInternal::get_string(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Vector2> { + static _FORCE_INLINE_ const Vector2 &get(const Variant *v) { return *VariantInternal::get_vector2(v); } + static _FORCE_INLINE_ void set(Variant *v, const Vector2 &p_value) { *VariantInternal::get_vector2(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Vector2i> { + static _FORCE_INLINE_ const Vector2i &get(const Variant *v) { return *VariantInternal::get_vector2i(v); } + static _FORCE_INLINE_ void set(Variant *v, const Vector2i &p_value) { *VariantInternal::get_vector2i(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Rect2> { + static _FORCE_INLINE_ const Rect2 &get(const Variant *v) { return *VariantInternal::get_rect2(v); } + static _FORCE_INLINE_ void set(Variant *v, const Rect2 &p_value) { *VariantInternal::get_rect2(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Rect2i> { + static _FORCE_INLINE_ const Rect2i &get(const Variant *v) { return *VariantInternal::get_rect2i(v); } + static _FORCE_INLINE_ void set(Variant *v, const Rect2i &p_value) { *VariantInternal::get_rect2i(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Vector3> { + static _FORCE_INLINE_ const Vector3 &get(const Variant *v) { return *VariantInternal::get_vector3(v); } + static _FORCE_INLINE_ void set(Variant *v, const Vector3 &p_value) { *VariantInternal::get_vector3(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Vector3i> { + static _FORCE_INLINE_ const Vector3i &get(const Variant *v) { return *VariantInternal::get_vector3i(v); } + static _FORCE_INLINE_ void set(Variant *v, const Vector3i &p_value) { *VariantInternal::get_vector3i(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Transform2D> { + static _FORCE_INLINE_ const Transform2D &get(const Variant *v) { return *VariantInternal::get_transform2d(v); } + static _FORCE_INLINE_ void set(Variant *v, const Transform2D &p_value) { *VariantInternal::get_transform2d(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Transform> { + static _FORCE_INLINE_ const Transform &get(const Variant *v) { return *VariantInternal::get_transform(v); } + static _FORCE_INLINE_ void set(Variant *v, const Transform &p_value) { *VariantInternal::get_transform(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Plane> { + static _FORCE_INLINE_ const Plane &get(const Variant *v) { return *VariantInternal::get_plane(v); } + static _FORCE_INLINE_ void set(Variant *v, const Plane &p_value) { *VariantInternal::get_plane(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Quat> { + static _FORCE_INLINE_ const Quat &get(const Variant *v) { return *VariantInternal::get_quat(v); } + static _FORCE_INLINE_ void set(Variant *v, const Quat &p_value) { *VariantInternal::get_quat(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<AABB> { + static _FORCE_INLINE_ const AABB &get(const Variant *v) { return *VariantInternal::get_aabb(v); } + static _FORCE_INLINE_ void set(Variant *v, const AABB &p_value) { *VariantInternal::get_aabb(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Basis> { + static _FORCE_INLINE_ const Basis &get(const Variant *v) { return *VariantInternal::get_basis(v); } + static _FORCE_INLINE_ void set(Variant *v, const Basis &p_value) { *VariantInternal::get_basis(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Color> { + static _FORCE_INLINE_ const Color &get(const Variant *v) { return *VariantInternal::get_color(v); } + static _FORCE_INLINE_ void set(Variant *v, const Color &p_value) { *VariantInternal::get_color(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<StringName> { + static _FORCE_INLINE_ const StringName &get(const Variant *v) { return *VariantInternal::get_string_name(v); } + static _FORCE_INLINE_ void set(Variant *v, const StringName &p_value) { *VariantInternal::get_string_name(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<NodePath> { + static _FORCE_INLINE_ const NodePath &get(const Variant *v) { return *VariantInternal::get_node_path(v); } + static _FORCE_INLINE_ void set(Variant *v, const NodePath &p_value) { *VariantInternal::get_node_path(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<::RID> { + static _FORCE_INLINE_ const ::RID &get(const Variant *v) { return *VariantInternal::get_rid(v); } + static _FORCE_INLINE_ void set(Variant *v, const ::RID &p_value) { *VariantInternal::get_rid(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Callable> { + static _FORCE_INLINE_ const Callable &get(const Variant *v) { return *VariantInternal::get_callable(v); } + static _FORCE_INLINE_ void set(Variant *v, const Callable &p_value) { *VariantInternal::get_callable(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Signal> { + static _FORCE_INLINE_ const Signal &get(const Variant *v) { return *VariantInternal::get_signal(v); } + static _FORCE_INLINE_ void set(Variant *v, const Signal &p_value) { *VariantInternal::get_signal(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Dictionary> { + static _FORCE_INLINE_ const Dictionary &get(const Variant *v) { return *VariantInternal::get_dictionary(v); } + static _FORCE_INLINE_ void set(Variant *v, const Dictionary &p_value) { *VariantInternal::get_dictionary(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Array> { + static _FORCE_INLINE_ const Array &get(const Variant *v) { return *VariantInternal::get_array(v); } + static _FORCE_INLINE_ void set(Variant *v, const Array &p_value) { *VariantInternal::get_array(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<PackedByteArray> { + static _FORCE_INLINE_ const PackedByteArray &get(const Variant *v) { return *VariantInternal::get_byte_array(v); } + static _FORCE_INLINE_ void set(Variant *v, const PackedByteArray &p_value) { *VariantInternal::get_byte_array(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<PackedInt32Array> { + static _FORCE_INLINE_ const PackedInt32Array &get(const Variant *v) { return *VariantInternal::get_int32_array(v); } + static _FORCE_INLINE_ void set(Variant *v, const PackedInt32Array &p_value) { *VariantInternal::get_int32_array(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<PackedInt64Array> { + static _FORCE_INLINE_ const PackedInt64Array &get(const Variant *v) { return *VariantInternal::get_int64_array(v); } + static _FORCE_INLINE_ void set(Variant *v, const PackedInt64Array &p_value) { *VariantInternal::get_int64_array(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<PackedFloat32Array> { + static _FORCE_INLINE_ const PackedFloat32Array &get(const Variant *v) { return *VariantInternal::get_float32_array(v); } + static _FORCE_INLINE_ void set(Variant *v, const PackedFloat32Array &p_value) { *VariantInternal::get_float32_array(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<PackedFloat64Array> { + static _FORCE_INLINE_ const PackedFloat64Array &get(const Variant *v) { return *VariantInternal::get_float64_array(v); } + static _FORCE_INLINE_ void set(Variant *v, const PackedFloat64Array &p_value) { *VariantInternal::get_float64_array(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<PackedStringArray> { + static _FORCE_INLINE_ const PackedStringArray &get(const Variant *v) { return *VariantInternal::get_string_array(v); } + static _FORCE_INLINE_ void set(Variant *v, const PackedStringArray &p_value) { *VariantInternal::get_string_array(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<PackedVector2Array> { + static _FORCE_INLINE_ const PackedVector2Array &get(const Variant *v) { return *VariantInternal::get_vector2_array(v); } + static _FORCE_INLINE_ void set(Variant *v, const PackedVector2Array &p_value) { *VariantInternal::get_vector2_array(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<PackedVector3Array> { + static _FORCE_INLINE_ const PackedVector3Array &get(const Variant *v) { return *VariantInternal::get_vector3_array(v); } + static _FORCE_INLINE_ void set(Variant *v, const PackedVector3Array &p_value) { *VariantInternal::get_vector3_array(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<PackedColorArray> { + static _FORCE_INLINE_ const PackedColorArray &get(const Variant *v) { return *VariantInternal::get_color_array(v); } + static _FORCE_INLINE_ void set(Variant *v, const PackedColorArray &p_value) { *VariantInternal::get_color_array(v) = p_value; } +}; + +template <> +struct VariantInternalAccessor<Object *> { + static _FORCE_INLINE_ Object *get(const Variant *v) { return const_cast<Object *>(*VariantInternal::get_object(v)); } + static _FORCE_INLINE_ void set(Variant *v, const Object *p_value) { *VariantInternal::get_object(v) = const_cast<Object *>(p_value); } +}; + +template <> +struct VariantInternalAccessor<Variant> { + static _FORCE_INLINE_ Variant &get(Variant *v) { return *v; } + static _FORCE_INLINE_ const Variant &get(const Variant *v) { return *v; } + static _FORCE_INLINE_ void set(Variant *v, const Variant &p_value) { *v = p_value; } +}; + +template <> +struct VariantInternalAccessor<Vector<Variant>> { + static _FORCE_INLINE_ Vector<Variant> get(const Variant *v) { + Vector<Variant> ret; + int s = VariantInternal::get_array(v)->size(); + ret.resize(s); + for (int i = 0; i < s; i++) { + ret.write[i] = VariantInternal::get_array(v)->get(i); + } + + return ret; + } + static _FORCE_INLINE_ void set(Variant *v, const Vector<Variant> &p_value) { + int s = p_value.size(); + VariantInternal::get_array(v)->resize(s); + for (int i = 0; i < s; i++) { + VariantInternal::get_array(v)->set(i, p_value[i]); + } + } +}; + +template <class T> +struct VariantInitializer { +}; + +template <> +struct VariantInitializer<bool> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<bool>(v); } +}; + +#define INITIALIZER_INT(m_type) \ + template <> \ + struct VariantInitializer<m_type> { \ + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<int64_t>(v); } \ + }; + +INITIALIZER_INT(uint8_t) +INITIALIZER_INT(int8_t) +INITIALIZER_INT(uint16_t) +INITIALIZER_INT(int16_t) +INITIALIZER_INT(uint32_t) +INITIALIZER_INT(int32_t) +INITIALIZER_INT(uint64_t) +INITIALIZER_INT(int64_t) +INITIALIZER_INT(char32_t) +INITIALIZER_INT(Error) +INITIALIZER_INT(ObjectID) + +template <> +struct VariantInitializer<double> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<double>(v); } +}; + +template <> +struct VariantInitializer<float> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<double>(v); } +}; + +template <> +struct VariantInitializer<String> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_string(v); } +}; + +template <> +struct VariantInitializer<Vector2> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector2>(v); } +}; + +template <> +struct VariantInitializer<Vector2i> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector2i>(v); } +}; + +template <> +struct VariantInitializer<Rect2> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Rect2>(v); } +}; + +template <> +struct VariantInitializer<Rect2i> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Rect2i>(v); } +}; + +template <> +struct VariantInitializer<Vector3> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector3>(v); } +}; + +template <> +struct VariantInitializer<Vector3i> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Vector3i>(v); } +}; + +template <> +struct VariantInitializer<Transform2D> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform2d(v); } +}; + +template <> +struct VariantInitializer<Plane> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Plane>(v); } +}; + +template <> +struct VariantInitializer<Quat> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Quat>(v); } +}; + +template <> +struct VariantInitializer<AABB> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_aabb(v); } +}; + +template <> +struct VariantInitializer<Basis> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_basis(v); } +}; + +template <> +struct VariantInitializer<Transform> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_transform(v); } +}; + +template <> +struct VariantInitializer<Color> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<Color>(v); } +}; + +template <> +struct VariantInitializer<StringName> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_string_name(v); } +}; + +template <> +struct VariantInitializer<NodePath> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_node_path(v); } +}; + +template <> +struct VariantInitializer<::RID> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_generic<::RID>(v); } +}; + +template <> +struct VariantInitializer<Callable> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_callable(v); } +}; + +template <> +struct VariantInitializer<Signal> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_signal(v); } +}; + +template <> +struct VariantInitializer<Dictionary> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_dictionary(v); } +}; + +template <> +struct VariantInitializer<Array> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_array(v); } +}; + +template <> +struct VariantInitializer<PackedByteArray> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_byte_array(v); } +}; + +template <> +struct VariantInitializer<PackedInt32Array> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_int32_array(v); } +}; + +template <> +struct VariantInitializer<PackedInt64Array> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_int64_array(v); } +}; + +template <> +struct VariantInitializer<PackedFloat32Array> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_float32_array(v); } +}; + +template <> +struct VariantInitializer<PackedFloat64Array> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_float64_array(v); } +}; + +template <> +struct VariantInitializer<PackedStringArray> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_string_array(v); } +}; + +template <> +struct VariantInitializer<PackedVector2Array> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_vector2_array(v); } +}; + +template <> +struct VariantInitializer<PackedVector3Array> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_vector3_array(v); } +}; + +template <> +struct VariantInitializer<PackedColorArray> { + static _FORCE_INLINE_ void init(Variant *v) { VariantInternal::init_color_array(v); } +}; + +template <class T> +struct VariantZeroAssigner { +}; + +template <> +struct VariantZeroAssigner<bool> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_bool(v) = false; } +}; + +template <> +struct VariantZeroAssigner<int64_t> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_int(v) = 0; } +}; + +template <> +struct VariantZeroAssigner<double> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_float(v) = 0.0; } +}; + +template <> +struct VariantZeroAssigner<float> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_float(v) = 0.0; } +}; + +template <> +struct VariantZeroAssigner<String> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<Vector2> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector2(v) = Vector2(); } +}; + +template <> +struct VariantZeroAssigner<Vector2i> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector2i(v) = Vector2i(); } +}; + +template <> +struct VariantZeroAssigner<Rect2> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_rect2(v) = Rect2(); } +}; + +template <> +struct VariantZeroAssigner<Rect2i> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_rect2i(v) = Rect2i(); } +}; + +template <> +struct VariantZeroAssigner<Vector3> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector3(v) = Vector3(); } +}; + +template <> +struct VariantZeroAssigner<Vector3i> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_vector3i(v) = Vector3i(); } +}; + +template <> +struct VariantZeroAssigner<Transform2D> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_transform2d(v) = Transform2D(); } +}; + +template <> +struct VariantZeroAssigner<Plane> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_plane(v) = Plane(); } +}; + +template <> +struct VariantZeroAssigner<Quat> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_quat(v) = Quat(); } +}; + +template <> +struct VariantZeroAssigner<AABB> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_aabb(v) = AABB(); } +}; + +template <> +struct VariantZeroAssigner<Basis> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_basis(v) = Basis(); } +}; + +template <> +struct VariantZeroAssigner<Transform> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_transform(v) = Transform(); } +}; + +template <> +struct VariantZeroAssigner<Color> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_color(v) = Color(); } +}; + +template <> +struct VariantZeroAssigner<StringName> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<NodePath> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<::RID> { + static _FORCE_INLINE_ void zero(Variant *v) { *VariantInternal::get_rid(v) = RID(); } +}; + +template <> +struct VariantZeroAssigner<Callable> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<Signal> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<Dictionary> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<Array> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<PackedByteArray> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<PackedInt32Array> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<PackedInt64Array> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<PackedFloat32Array> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<PackedFloat64Array> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<PackedStringArray> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<PackedVector2Array> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<PackedVector3Array> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <> +struct VariantZeroAssigner<PackedColorArray> { + static _FORCE_INLINE_ void zero(Variant *v) {} +}; + +template <class T> +struct VariantTypeChanger { + static _FORCE_INLINE_ void change(Variant *v) { + if (v->get_type() != GetTypeInfo<T>::VARIANT_TYPE || GetTypeInfo<T>::VARIANT_TYPE >= Variant::PACKED_BYTE_ARRAY) { //second condition removed by optimizer + VariantInternal::clear(v); + VariantInitializer<T>::init(v); + } + } + static _FORCE_INLINE_ void change_and_reset(Variant *v) { + if (v->get_type() != GetTypeInfo<T>::VARIANT_TYPE || GetTypeInfo<T>::VARIANT_TYPE >= Variant::PACKED_BYTE_ARRAY) { //second condition removed by optimizer + VariantInternal::clear(v); + VariantInitializer<T>::init(v); + } + + VariantZeroAssigner<T>::zero(v); + } +}; + +template <class T> +struct VariantTypeAdjust { + _FORCE_INLINE_ static void adjust(Variant *r_ret) { + VariantTypeChanger<typename GetSimpleTypeT<T>::type_t>::change(r_ret); + } +}; + +template <> +struct VariantTypeAdjust<Variant> { + _FORCE_INLINE_ static void adjust(Variant *r_ret) { + // Do nothing for variant. + } +}; + +template <> +struct VariantTypeAdjust<Object *> { + _FORCE_INLINE_ static void adjust(Variant *r_ret) { + VariantInternal::clear(r_ret); + *r_ret = (Object *)nullptr; + } +}; + +#endif // VARIANT_INTERNAL_H diff --git a/core/variant/variant_op.cpp b/core/variant/variant_op.cpp new file mode 100644 index 0000000000..e9c817bc9f --- /dev/null +++ b/core/variant/variant_op.cpp @@ -0,0 +1,2017 @@ +/*************************************************************************/ +/* variant_op.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "variant.h" + +#include "core/core_string_names.h" +#include "core/debugger/engine_debugger.h" +#include "core/object/class_db.h" + +template <class R, class A, class B> +class OperatorEvaluatorAdd { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a + b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) + *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left) + PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> +class OperatorEvaluatorSub { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a - b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) - *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left) - PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> +class OperatorEvaluatorMul { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a * b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) * *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left) * PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> +class OperatorEvaluatorXForm { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a.xform(b); + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = VariantGetInternalPtr<A>::get_ptr(left)->xform(*VariantGetInternalPtr<B>::get_ptr(right)); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left).xform(PtrToArg<B>::convert(right)), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> +class OperatorEvaluatorXFormInv { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = b.xform_inv(a); + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = VariantGetInternalPtr<B>::get_ptr(right)->xform_inv(*VariantGetInternalPtr<A>::get_ptr(left)); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<B>::convert(right).xform_inv(PtrToArg<A>::convert(left)), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> +class OperatorEvaluatorDiv { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a / b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) / *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left) / PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> +class OperatorEvaluatorDivNZ { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + if (b == 0) { + r_valid = false; + *r_ret = "Division by zero error"; + return; + } + *r_ret = a / b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) / *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left) / PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> +class OperatorEvaluatorMod { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a % b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) % *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left) % PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> +class OperatorEvaluatorModNZ { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + if (b == 0) { + r_valid = false; + *r_ret = "Module by zero error"; + return; + } + *r_ret = a % b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) % *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left) % PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A> +class OperatorEvaluatorNeg { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + *r_ret = -a; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = -*VariantGetInternalPtr<A>::get_ptr(left); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(-PtrToArg<A>::convert(left), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A> +class OperatorEvaluatorPos { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + *r_ret = a; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> +class OperatorEvaluatorShiftLeft { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a << b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) << *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left) << PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> +class OperatorEvaluatorShiftRight { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a >> b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) >> *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left) >> PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> +class OperatorEvaluatorBitOr { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a | b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) | *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left) | PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> +class OperatorEvaluatorBitAnd { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a & b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) & *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left) & PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A, class B> +class OperatorEvaluatorBitXor { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a ^ b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) ^ *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(PtrToArg<A>::convert(left) ^ PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class R, class A> +class OperatorEvaluatorBitNeg { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + *r_ret = ~a; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<R>::change(r_ret); + *VariantGetInternalPtr<R>::get_ptr(r_ret) = ~*VariantGetInternalPtr<A>::get_ptr(left); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<R>::encode(~PtrToArg<A>::convert(left), r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; } +}; + +template <class A, class B> +class OperatorEvaluatorEqual { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a == b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) == *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<A>::convert(left) == PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorEqualObject { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Object *a = p_left.get_validated_object(); + const Object *b = p_right.get_validated_object(); + *r_ret = a == b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + const Object *a = left->get_validated_object(); + const Object *b = right->get_validated_object(); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = a == b; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) == PtrToArg<Object *>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorEqualObjectNil { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Object *a = p_left.get_validated_object(); + *r_ret = a == nullptr; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + const Object *a = left->get_validated_object(); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = a == nullptr; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) == nullptr, r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorEqualNilObject { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Object *b = p_right.get_validated_object(); + *r_ret = nullptr == b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + const Object *b = right->get_validated_object(); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = nullptr == b; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(nullptr == PtrToArg<Object *>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +template <class A, class B> +class OperatorEvaluatorNotEqual { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a != b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) != *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<A>::convert(left) != PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorNotEqualObject { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + Object *a = p_left.get_validated_object(); + Object *b = p_right.get_validated_object(); + *r_ret = a != b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + Object *a = left->get_validated_object(); + Object *b = right->get_validated_object(); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = a != b; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) != PtrToArg<Object *>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorNotEqualObjectNil { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + Object *a = p_left.get_validated_object(); + *r_ret = a != nullptr; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + Object *a = left->get_validated_object(); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = a != nullptr; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) != nullptr, r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorNotEqualNilObject { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + Object *b = p_right.get_validated_object(); + *r_ret = nullptr != b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + Object *b = right->get_validated_object(); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = nullptr != b; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(nullptr != PtrToArg<Object *>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +template <class A, class B> +class OperatorEvaluatorLess { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a < b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) < *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<A>::convert(left) < PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +template <class A, class B> +class OperatorEvaluatorLessEqual { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a <= b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) <= *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<A>::convert(left) <= PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +template <class A, class B> +class OperatorEvaluatorGreater { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a > b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) > *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<A>::convert(left) > PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +template <class A, class B> +class OperatorEvaluatorGreaterEqual { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a >= b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) >= *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<A>::convert(left) >= PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +template <class A, class B> +class OperatorEvaluatorAnd { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a && b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) && *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<A>::convert(left) && PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +template <class A, class B> +class OperatorEvaluatorOr { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = a || b; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = *VariantGetInternalPtr<A>::get_ptr(left) || *VariantGetInternalPtr<B>::get_ptr(right); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<A>::convert(left) || PtrToArg<B>::convert(right), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +#define XOR_OP(m_a, m_b) (((m_a) || (m_b)) && !((m_a) && (m_b))) +template <class A, class B> +class OperatorEvaluatorXor { +public: + _FORCE_INLINE_ static bool xor_op(const A &a, const B &b) { + return ((a) || (b)) && !((a) && (b)); + } + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + *r_ret = xor_op(a, b); + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = xor_op(*VariantGetInternalPtr<A>::get_ptr(left), *VariantGetInternalPtr<B>::get_ptr(right)); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(xor_op(PtrToArg<A>::convert(left), PtrToArg<B>::convert(right)), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +template <class A> +class OperatorEvaluatorNot { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + *r_ret = !a; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<A>::get_ptr(left); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(!PtrToArg<A>::convert(left)); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +//// CUSTOM //// + +class OperatorEvaluatorAddArray { +public: + _FORCE_INLINE_ static void _add_arrays(Array &sum, const Array &array_a, const Array &array_b) { + int asize = array_a.size(); + int bsize = array_b.size(); + sum.resize(asize + bsize); + for (int i = 0; i < asize; i++) { + sum[i] = array_a[i]; + } + for (int i = 0; i < bsize; i++) { + sum[i + asize] = array_b[i]; + } + } + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Array &array_a = *VariantGetInternalPtr<Array>::get_ptr(&p_left); + const Array &array_b = *VariantGetInternalPtr<Array>::get_ptr(&p_right); + Array sum; + _add_arrays(sum, array_a, array_b); + *r_ret = sum; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<Array>::change(r_ret); + _add_arrays(*VariantGetInternalPtr<Array>::get_ptr(r_ret), *VariantGetInternalPtr<Array>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right)); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + Array ret; + _add_arrays(ret, PtrToArg<Array>::convert(left), PtrToArg<Array>::convert(right)); + PtrToArg<Array>::encode(ret, r_ret); + } + static Variant::Type get_return_type() { return Variant::ARRAY; } +}; + +template <class T> +class OperatorEvaluatorAppendArray { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Vector<T> &array_a = *VariantGetInternalPtr<Vector<T>>::get_ptr(&p_left); + const Vector<T> &array_b = *VariantGetInternalPtr<Vector<T>>::get_ptr(&p_right); + Vector<T> sum = array_a; + sum.append_array(array_b); + *r_ret = sum; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<Vector<T>>::change(r_ret); + *VariantGetInternalPtr<Vector<T>>::get_ptr(r_ret) = *VariantGetInternalPtr<Vector<T>>::get_ptr(left); + VariantGetInternalPtr<Vector<T>>::get_ptr(r_ret)->append_array(*VariantGetInternalPtr<Vector<T>>::get_ptr(right)); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + Vector<T> sum = PtrToArg<Vector<T>>::convert(left); + sum.append_array(PtrToArg<Vector<T>>::convert(right)); + PtrToArg<Vector<T>>::encode(sum, r_ret); + } + static Variant::Type get_return_type() { return GetTypeInfo<Vector<T>>::VARIANT_TYPE; } +}; + +class OperatorEvaluatorStringModNil { +public: + _FORCE_INLINE_ static String do_mod(const String &s, bool *r_valid) { + Array values; + values.push_back(Variant()); + + String a = s.sprintf(values, r_valid); + if (r_valid) { + *r_valid = !*r_valid; + } + return a; + } + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left); + *r_ret = do_mod(a, &r_valid); + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<String>::change(r_ret); + *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), nullptr); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), nullptr), r_ret); + } + static Variant::Type get_return_type() { return Variant::STRING; } +}; + +class OperatorEvaluatorStringModArray { +public: + _FORCE_INLINE_ static String do_mod(const String &s, const Array &p_values, bool *r_valid) { + String a = s.sprintf(p_values, r_valid); + if (r_valid) { + *r_valid = !*r_valid; + } + return a; + } + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left); + *r_ret = do_mod(a, *VariantGetInternalPtr<Array>::get_ptr(&p_right), &r_valid); + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<String>::change(r_ret); + *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right), nullptr); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<Array>::convert(right), nullptr), r_ret); + } + static Variant::Type get_return_type() { return Variant::STRING; } +}; + +class OperatorEvaluatorStringModObject { +public: + _FORCE_INLINE_ static String do_mod(const String &s, const Object *p_object, bool *r_valid) { + Array values; + values.push_back(p_object); + String a = s.sprintf(values, r_valid); + if (r_valid) { + *r_valid = !*r_valid; + } + + return a; + } + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left); + *r_ret = do_mod(a, p_right.get_validated_object(), &r_valid); + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<String>::change(r_ret); + *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), right->get_validated_object(), nullptr); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<Object *>::convert(right), nullptr), r_ret); + } + static Variant::Type get_return_type() { return Variant::STRING; } +}; + +template <class T> +class OperatorEvaluatorStringModT { +public: + _FORCE_INLINE_ static String do_mod(const String &s, const T &p_value, bool *r_valid) { + Array values; + values.push_back(p_value); + String a = s.sprintf(values, r_valid); + if (r_valid) { + *r_valid = !*r_valid; + } + return a; + } + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left); + *r_ret = do_mod(a, *VariantGetInternalPtr<T>::get_ptr(&p_right), &r_valid); + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<String>::change(r_ret); + *VariantGetInternalPtr<String>::get_ptr(r_ret) = do_mod(*VariantGetInternalPtr<String>::get_ptr(left), *VariantGetInternalPtr<T>::get_ptr(right), nullptr); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<String>::encode(do_mod(PtrToArg<String>::convert(left), PtrToArg<T>::convert(right), nullptr), r_ret); + } + static Variant::Type get_return_type() { return Variant::STRING; } +}; + +template <Variant::Operator op, Variant::Type type_left, Variant::Type type_right> +class OperatorEvaluatorAlwaysTrue { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + *r_ret = true; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = true; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(true, r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +template <Variant::Operator op, Variant::Type type_left, Variant::Type type_right> +class OperatorEvaluatorAlwaysFalse { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + *r_ret = false; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = false; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(false, r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +///// OR /////// + +_FORCE_INLINE_ static bool _operate_or(bool p_left, bool p_right) { + return p_left || p_right; +} + +_FORCE_INLINE_ static bool _operate_and(bool p_left, bool p_right) { + return p_left && p_right; +} + +_FORCE_INLINE_ static bool _operate_xor(bool p_left, bool p_right) { + return (p_left || p_right) && !(p_left && p_right); +} + +_FORCE_INLINE_ static bool _operate_get_nil(const Variant *p_ptr) { + return p_ptr->get_validated_object() != nullptr; +} + +_FORCE_INLINE_ static bool _operate_get_bool(const Variant *p_ptr) { + return *VariantGetInternalPtr<bool>::get_ptr(p_ptr); +} + +_FORCE_INLINE_ static bool _operate_get_int(const Variant *p_ptr) { + return *VariantGetInternalPtr<int64_t>::get_ptr(p_ptr) != 0; +} + +_FORCE_INLINE_ static bool _operate_get_float(const Variant *p_ptr) { + return *VariantGetInternalPtr<double>::get_ptr(p_ptr) != 0.0; +} + +_FORCE_INLINE_ static bool _operate_get_object(const Variant *p_ptr) { + return p_ptr->get_validated_object() != nullptr; +} + +_FORCE_INLINE_ static bool _operate_get_ptr_nil(const void *p_ptr) { + return false; +} + +_FORCE_INLINE_ static bool _operate_get_ptr_bool(const void *p_ptr) { + return PtrToArg<bool>::convert(p_ptr); +} + +_FORCE_INLINE_ static bool _operate_get_ptr_int(const void *p_ptr) { + return PtrToArg<int64_t>::convert(p_ptr) != 0; +} + +_FORCE_INLINE_ static bool _operate_get_ptr_float(const void *p_ptr) { + return PtrToArg<double>::convert(p_ptr) != 0.0; +} + +_FORCE_INLINE_ static bool _operate_get_ptr_object(const void *p_ptr) { + return PtrToArg<Object *>::convert(p_ptr) != nullptr; +} + +#define OP_EVALUATOR(m_class_name, m_left, m_right, m_op) \ + class m_class_name { \ + public: \ + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { \ + *r_ret = m_op(_operate_get_##m_left(&p_left), _operate_get_##m_right(&p_right)); \ + r_valid = true; \ + } \ + \ + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { \ + VariantTypeChanger<bool>::change(r_ret); \ + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = m_op(_operate_get_##m_left(left), _operate_get_##m_right(right)); \ + } \ + \ + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { \ + PtrToArg<bool>::encode(m_op(_operate_get_ptr_##m_left(left), _operate_get_ptr_##m_right(right)), r_ret); \ + } \ + \ + static Variant::Type get_return_type() { \ + return Variant::BOOL; \ + } \ + }; + +// OR + +// nil +OP_EVALUATOR(OperatorEvaluatorNilXBoolOr, nil, bool, _operate_or) +OP_EVALUATOR(OperatorEvaluatorBoolXNilOr, bool, nil, _operate_or) + +OP_EVALUATOR(OperatorEvaluatorNilXIntOr, nil, int, _operate_or) +OP_EVALUATOR(OperatorEvaluatorIntXNilOr, int, nil, _operate_or) + +OP_EVALUATOR(OperatorEvaluatorNilXFloatOr, nil, float, _operate_or) +OP_EVALUATOR(OperatorEvaluatorFloatXNilOr, float, nil, _operate_or) + +OP_EVALUATOR(OperatorEvaluatorObjectXNilOr, object, nil, _operate_or) +OP_EVALUATOR(OperatorEvaluatorNilXObjectOr, nil, object, _operate_or) + +// bool +OP_EVALUATOR(OperatorEvaluatorBoolXBoolOr, bool, bool, _operate_or) + +OP_EVALUATOR(OperatorEvaluatorBoolXIntOr, bool, int, _operate_or) +OP_EVALUATOR(OperatorEvaluatorIntXBoolOr, int, bool, _operate_or) + +OP_EVALUATOR(OperatorEvaluatorBoolXFloatOr, bool, float, _operate_or) +OP_EVALUATOR(OperatorEvaluatorFloatXBoolOr, float, bool, _operate_or) + +OP_EVALUATOR(OperatorEvaluatorBoolXObjectOr, bool, object, _operate_or) +OP_EVALUATOR(OperatorEvaluatorObjectXBoolOr, object, bool, _operate_or) + +// int +OP_EVALUATOR(OperatorEvaluatorIntXIntOr, int, int, _operate_or) + +OP_EVALUATOR(OperatorEvaluatorIntXFloatOr, int, float, _operate_or) +OP_EVALUATOR(OperatorEvaluatorFloatXIntOr, float, int, _operate_or) + +OP_EVALUATOR(OperatorEvaluatorIntXObjectOr, int, object, _operate_or) +OP_EVALUATOR(OperatorEvaluatorObjectXIntOr, object, int, _operate_or) + +// float +OP_EVALUATOR(OperatorEvaluatorFloatXFloatOr, float, float, _operate_or) + +OP_EVALUATOR(OperatorEvaluatorFloatXObjectOr, float, object, _operate_or) +OP_EVALUATOR(OperatorEvaluatorObjectXFloatOr, object, float, _operate_or) + +// object +OP_EVALUATOR(OperatorEvaluatorObjectXObjectOr, object, object, _operate_or) + +// AND + +// nil +OP_EVALUATOR(OperatorEvaluatorNilXBoolAnd, nil, bool, _operate_and) +OP_EVALUATOR(OperatorEvaluatorBoolXNilAnd, bool, nil, _operate_and) + +OP_EVALUATOR(OperatorEvaluatorNilXIntAnd, nil, int, _operate_and) +OP_EVALUATOR(OperatorEvaluatorIntXNilAnd, int, nil, _operate_and) + +OP_EVALUATOR(OperatorEvaluatorNilXFloatAnd, nil, float, _operate_and) +OP_EVALUATOR(OperatorEvaluatorFloatXNilAnd, float, nil, _operate_and) + +OP_EVALUATOR(OperatorEvaluatorObjectXNilAnd, object, nil, _operate_and) +OP_EVALUATOR(OperatorEvaluatorNilXObjectAnd, nil, object, _operate_and) + +// bool +OP_EVALUATOR(OperatorEvaluatorBoolXBoolAnd, bool, bool, _operate_and) + +OP_EVALUATOR(OperatorEvaluatorBoolXIntAnd, bool, int, _operate_and) +OP_EVALUATOR(OperatorEvaluatorIntXBoolAnd, int, bool, _operate_and) + +OP_EVALUATOR(OperatorEvaluatorBoolXFloatAnd, bool, float, _operate_and) +OP_EVALUATOR(OperatorEvaluatorFloatXBoolAnd, float, bool, _operate_and) + +OP_EVALUATOR(OperatorEvaluatorBoolXObjectAnd, bool, object, _operate_and) +OP_EVALUATOR(OperatorEvaluatorObjectXBoolAnd, object, bool, _operate_and) + +// int +OP_EVALUATOR(OperatorEvaluatorIntXIntAnd, int, int, _operate_and) + +OP_EVALUATOR(OperatorEvaluatorIntXFloatAnd, int, float, _operate_and) +OP_EVALUATOR(OperatorEvaluatorFloatXIntAnd, float, int, _operate_and) + +OP_EVALUATOR(OperatorEvaluatorIntXObjectAnd, int, object, _operate_and) +OP_EVALUATOR(OperatorEvaluatorObjectXIntAnd, object, int, _operate_and) + +// float +OP_EVALUATOR(OperatorEvaluatorFloatXFloatAnd, float, float, _operate_and) + +OP_EVALUATOR(OperatorEvaluatorFloatXObjectAnd, float, object, _operate_and) +OP_EVALUATOR(OperatorEvaluatorObjectXFloatAnd, object, float, _operate_and) + +// object +OP_EVALUATOR(OperatorEvaluatorObjectXObjectAnd, object, object, _operate_and) + +// XOR + +// nil +OP_EVALUATOR(OperatorEvaluatorNilXBoolXor, nil, bool, _operate_xor) +OP_EVALUATOR(OperatorEvaluatorBoolXNilXor, bool, nil, _operate_xor) + +OP_EVALUATOR(OperatorEvaluatorNilXIntXor, nil, int, _operate_xor) +OP_EVALUATOR(OperatorEvaluatorIntXNilXor, int, nil, _operate_xor) + +OP_EVALUATOR(OperatorEvaluatorNilXFloatXor, nil, float, _operate_xor) +OP_EVALUATOR(OperatorEvaluatorFloatXNilXor, float, nil, _operate_xor) + +OP_EVALUATOR(OperatorEvaluatorObjectXNilXor, object, nil, _operate_xor) +OP_EVALUATOR(OperatorEvaluatorNilXObjectXor, nil, object, _operate_xor) + +// bool +OP_EVALUATOR(OperatorEvaluatorBoolXBoolXor, bool, bool, _operate_xor) + +OP_EVALUATOR(OperatorEvaluatorBoolXIntXor, bool, int, _operate_xor) +OP_EVALUATOR(OperatorEvaluatorIntXBoolXor, int, bool, _operate_xor) + +OP_EVALUATOR(OperatorEvaluatorBoolXFloatXor, bool, float, _operate_xor) +OP_EVALUATOR(OperatorEvaluatorFloatXBoolXor, float, bool, _operate_xor) + +OP_EVALUATOR(OperatorEvaluatorBoolXObjectXor, bool, object, _operate_xor) +OP_EVALUATOR(OperatorEvaluatorObjectXBoolXor, object, bool, _operate_xor) + +// int +OP_EVALUATOR(OperatorEvaluatorIntXIntXor, int, int, _operate_xor) + +OP_EVALUATOR(OperatorEvaluatorIntXFloatXor, int, float, _operate_xor) +OP_EVALUATOR(OperatorEvaluatorFloatXIntXor, float, int, _operate_xor) + +OP_EVALUATOR(OperatorEvaluatorIntXObjectXor, int, object, _operate_xor) +OP_EVALUATOR(OperatorEvaluatorObjectXIntXor, object, int, _operate_xor) + +// float +OP_EVALUATOR(OperatorEvaluatorFloatXFloatXor, float, float, _operate_xor) + +OP_EVALUATOR(OperatorEvaluatorFloatXObjectXor, float, object, _operate_xor) +OP_EVALUATOR(OperatorEvaluatorObjectXFloatXor, object, float, _operate_xor) + +// object +OP_EVALUATOR(OperatorEvaluatorObjectXObjectXor, object, object, _operate_xor) + +class OperatorEvaluatorNotBool { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + *r_ret = !*VariantGetInternalPtr<bool>::get_ptr(&p_left); + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<bool>::get_ptr(left); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(!PtrToArg<bool>::convert(left), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorNotInt { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + *r_ret = !*VariantGetInternalPtr<int64_t>::get_ptr(&p_left); + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<int64_t>::get_ptr(left); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(!PtrToArg<int64_t>::convert(left), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorNotFloat { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + *r_ret = !*VariantGetInternalPtr<double>::get_ptr(&p_left); + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = !*VariantGetInternalPtr<double>::get_ptr(left); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(!PtrToArg<double>::convert(left), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorNotObject { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + *r_ret = p_left.get_validated_object() == nullptr; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = left->get_validated_object() == nullptr; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<Object *>::convert(left) == nullptr, r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +//// + +class OperatorEvaluatorInStringFind { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const String &str_a = *VariantGetInternalPtr<String>::get_ptr(&p_left); + const String &str_b = *VariantGetInternalPtr<String>::get_ptr(&p_right); + + *r_ret = str_b.find(str_a) != -1; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + const String &str_a = *VariantGetInternalPtr<String>::get_ptr(left); + const String &str_b = *VariantGetInternalPtr<String>::get_ptr(right); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = str_b.find(str_a) != -1; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<String>::convert(right).find(PtrToArg<String>::convert(left)) != -1, r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +template <class A, class B> +class OperatorEvaluatorInArrayFind { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right); + + *r_ret = b.find(a) != -1; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + const A &a = *VariantGetInternalPtr<A>::get_ptr(left); + const B &b = *VariantGetInternalPtr<B>::get_ptr(right); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(a) != -1; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<B>::convert(right).find(PtrToArg<A>::convert(left)) != -1, r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorInArrayFindNil { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Array &b = *VariantGetInternalPtr<Array>::get_ptr(&p_right); + *r_ret = b.find(Variant()) != -1; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + const Array &b = *VariantGetInternalPtr<Array>::get_ptr(right); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(Variant()) != -1; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<Array>::convert(right).find(Variant()) != -1, r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorInArrayFindObject { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Array &b = *VariantGetInternalPtr<Array>::get_ptr(&p_right); + *r_ret = b.find(p_left) != -1; + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + const Array &b = *VariantGetInternalPtr<Array>::get_ptr(right); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.find(*left) != -1; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<Array>::convert(right).find(PtrToArg<Object *>::convert(left)) != -1, r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +template <class A> +class OperatorEvaluatorInDictionaryHas { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(&p_right); + const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left); + + *r_ret = b.has(a); + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right); + const A &a = *VariantGetInternalPtr<A>::get_ptr(left); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(a); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<Dictionary>::convert(right).has(PtrToArg<A>::convert(left)), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorInDictionaryHasNil { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(&p_right); + + *r_ret = b.has(Variant()); + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(Variant()); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<Dictionary>::convert(right).has(Variant()), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorInDictionaryHasObject { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(&p_right); + + *r_ret = b.has(p_left); + r_valid = true; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + const Dictionary &b = *VariantGetInternalPtr<Dictionary>::get_ptr(right); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = b.has(*left); + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + PtrToArg<bool>::encode(PtrToArg<Dictionary>::convert(right).has(PtrToArg<Object *>::convert(left)), r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorObjectHasPropertyString { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + Object *b = p_right.get_validated_object(); + if (!b) { + *r_ret = "Invalid base object for 'in'"; + r_valid = false; + return; + } + + const String &a = *VariantGetInternalPtr<String>::get_ptr(&p_left); + + b->get(a, &r_valid); + *r_ret = r_valid; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + Object *l = right->get_validated_object(); + ERR_FAIL_COND(l == nullptr); + const String &a = *VariantGetInternalPtr<String>::get_ptr(left); + + bool valid; + l->get(a, &valid); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = valid; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + bool valid; + PtrToArg<Object *>::convert(right)->get(PtrToArg<String>::convert(left), &valid); + PtrToArg<bool>::encode(valid, r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +class OperatorEvaluatorObjectHasPropertyStringName { +public: + static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) { + Object *b = p_right.get_validated_object(); + if (!b) { + *r_ret = "Invalid base object for 'in'"; + r_valid = false; + return; + } + + const StringName &a = *VariantGetInternalPtr<StringName>::get_ptr(&p_left); + + b->get(a, &r_valid); + *r_ret = r_valid; + } + static void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) { + Object *l = right->get_validated_object(); + ERR_FAIL_COND(l == nullptr); + const StringName &a = *VariantGetInternalPtr<StringName>::get_ptr(left); + + bool valid; + l->get(a, &valid); + VariantTypeChanger<bool>::change(r_ret); + *VariantGetInternalPtr<bool>::get_ptr(r_ret) = valid; + } + static void ptr_evaluate(const void *left, const void *right, void *r_ret) { + bool valid; + PtrToArg<Object *>::convert(right)->get(PtrToArg<StringName>::convert(left), &valid); + PtrToArg<bool>::encode(valid, r_ret); + } + static Variant::Type get_return_type() { return Variant::BOOL; } +}; + +typedef void (*VariantEvaluatorFunction)(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid); + +static Variant::Type operator_return_type_table[Variant::OP_MAX][Variant::VARIANT_MAX][Variant::VARIANT_MAX]; +static VariantEvaluatorFunction operator_evaluator_table[Variant::OP_MAX][Variant::VARIANT_MAX][Variant::VARIANT_MAX]; +static Variant::ValidatedOperatorEvaluator validated_operator_evaluator_table[Variant::OP_MAX][Variant::VARIANT_MAX][Variant::VARIANT_MAX]; +static Variant::PTROperatorEvaluator ptr_operator_evaluator_table[Variant::OP_MAX][Variant::VARIANT_MAX][Variant::VARIANT_MAX]; + +template <class T> +void register_op(Variant::Operator p_op, Variant::Type p_type_a, Variant::Type p_type_b) { + operator_return_type_table[p_op][p_type_a][p_type_b] = T::get_return_type(); + operator_evaluator_table[p_op][p_type_a][p_type_b] = T::evaluate; + validated_operator_evaluator_table[p_op][p_type_a][p_type_b] = T::validated_evaluate; + ptr_operator_evaluator_table[p_op][p_type_a][p_type_b] = T::ptr_evaluate; +} + +void Variant::_register_variant_operators() { + zeromem(operator_return_type_table, sizeof(operator_return_type_table)); + zeromem(operator_evaluator_table, sizeof(operator_evaluator_table)); + zeromem(validated_operator_evaluator_table, sizeof(validated_operator_evaluator_table)); + zeromem(ptr_operator_evaluator_table, sizeof(ptr_operator_evaluator_table)); + + register_op<OperatorEvaluatorAdd<int64_t, int64_t, int64_t>>(Variant::OP_ADD, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorAdd<double, int64_t, double>>(Variant::OP_ADD, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorAdd<double, double, int64_t>>(Variant::OP_ADD, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorAdd<double, double, double>>(Variant::OP_ADD, Variant::FLOAT, Variant::FLOAT); + register_op<OperatorEvaluatorAdd<String, String, String>>(Variant::OP_ADD, Variant::STRING, Variant::STRING); + register_op<OperatorEvaluatorAdd<Vector2, Vector2, Vector2>>(Variant::OP_ADD, Variant::VECTOR2, Variant::VECTOR2); + register_op<OperatorEvaluatorAdd<Vector2i, Vector2i, Vector2i>>(Variant::OP_ADD, Variant::VECTOR2I, Variant::VECTOR2I); + register_op<OperatorEvaluatorAdd<Vector3, Vector3, Vector3>>(Variant::OP_ADD, Variant::VECTOR3, Variant::VECTOR3); + register_op<OperatorEvaluatorAdd<Vector3i, Vector3i, Vector3i>>(Variant::OP_ADD, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorAdd<Quat, Quat, Quat>>(Variant::OP_ADD, Variant::QUAT, Variant::QUAT); + register_op<OperatorEvaluatorAdd<Color, Color, Color>>(Variant::OP_ADD, Variant::COLOR, Variant::COLOR); + register_op<OperatorEvaluatorAddArray>(Variant::OP_ADD, Variant::ARRAY, Variant::ARRAY); + register_op<OperatorEvaluatorAppendArray<uint8_t>>(Variant::OP_ADD, Variant::PACKED_BYTE_ARRAY, Variant::PACKED_BYTE_ARRAY); + register_op<OperatorEvaluatorAppendArray<int32_t>>(Variant::OP_ADD, Variant::PACKED_INT32_ARRAY, Variant::PACKED_INT32_ARRAY); + register_op<OperatorEvaluatorAppendArray<int64_t>>(Variant::OP_ADD, Variant::PACKED_INT64_ARRAY, Variant::PACKED_INT64_ARRAY); + register_op<OperatorEvaluatorAppendArray<float>>(Variant::OP_ADD, Variant::PACKED_FLOAT32_ARRAY, Variant::PACKED_FLOAT32_ARRAY); + register_op<OperatorEvaluatorAppendArray<double>>(Variant::OP_ADD, Variant::PACKED_FLOAT64_ARRAY, Variant::PACKED_FLOAT64_ARRAY); + register_op<OperatorEvaluatorAppendArray<String>>(Variant::OP_ADD, Variant::PACKED_STRING_ARRAY, Variant::PACKED_STRING_ARRAY); + register_op<OperatorEvaluatorAppendArray<Vector2>>(Variant::OP_ADD, Variant::PACKED_VECTOR2_ARRAY, Variant::PACKED_VECTOR2_ARRAY); + register_op<OperatorEvaluatorAppendArray<Vector3>>(Variant::OP_ADD, Variant::PACKED_VECTOR3_ARRAY, Variant::PACKED_VECTOR3_ARRAY); + register_op<OperatorEvaluatorAppendArray<Color>>(Variant::OP_ADD, Variant::PACKED_COLOR_ARRAY, Variant::PACKED_COLOR_ARRAY); + + register_op<OperatorEvaluatorSub<int64_t, int64_t, int64_t>>(Variant::OP_SUBTRACT, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorSub<double, int64_t, double>>(Variant::OP_SUBTRACT, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorSub<double, double, int64_t>>(Variant::OP_SUBTRACT, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorSub<double, double, double>>(Variant::OP_SUBTRACT, Variant::FLOAT, Variant::FLOAT); + register_op<OperatorEvaluatorSub<Vector2, Vector2, Vector2>>(Variant::OP_SUBTRACT, Variant::VECTOR2, Variant::VECTOR2); + register_op<OperatorEvaluatorSub<Vector2i, Vector2i, Vector2i>>(Variant::OP_SUBTRACT, Variant::VECTOR2I, Variant::VECTOR2I); + register_op<OperatorEvaluatorSub<Vector3, Vector3, Vector3>>(Variant::OP_SUBTRACT, Variant::VECTOR3, Variant::VECTOR3); + register_op<OperatorEvaluatorSub<Vector3i, Vector3i, Vector3i>>(Variant::OP_SUBTRACT, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorSub<Quat, Quat, Quat>>(Variant::OP_SUBTRACT, Variant::QUAT, Variant::QUAT); + register_op<OperatorEvaluatorSub<Color, Color, Color>>(Variant::OP_SUBTRACT, Variant::COLOR, Variant::COLOR); + + register_op<OperatorEvaluatorMul<int64_t, int64_t, int64_t>>(Variant::OP_MULTIPLY, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorMul<double, int64_t, double>>(Variant::OP_MULTIPLY, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorMul<Vector2, int64_t, Vector2>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR2); + register_op<OperatorEvaluatorMul<Vector2i, int64_t, Vector2i>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR2I); + register_op<OperatorEvaluatorMul<Vector3, int64_t, Vector3>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR3); + register_op<OperatorEvaluatorMul<Vector3i, int64_t, Vector3i>>(Variant::OP_MULTIPLY, Variant::INT, Variant::VECTOR3I); + + register_op<OperatorEvaluatorMul<double, double, double>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::FLOAT); + register_op<OperatorEvaluatorMul<double, double, int64_t>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorMul<Vector2, double, Vector2>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR2); + register_op<OperatorEvaluatorMul<Vector2i, double, Vector2i>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR2I); + register_op<OperatorEvaluatorMul<Vector3, double, Vector3>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR3); + register_op<OperatorEvaluatorMul<Vector3i, double, Vector3i>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::VECTOR3I); + + register_op<OperatorEvaluatorMul<Vector2, Vector2, Vector2>>(Variant::OP_MULTIPLY, Variant::VECTOR2, Variant::VECTOR2); + register_op<OperatorEvaluatorMul<Vector2, Vector2, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR2, Variant::INT); + register_op<OperatorEvaluatorMul<Vector2, Vector2, double>>(Variant::OP_MULTIPLY, Variant::VECTOR2, Variant::FLOAT); + + register_op<OperatorEvaluatorMul<Vector2i, Vector2i, Vector2i>>(Variant::OP_MULTIPLY, Variant::VECTOR2I, Variant::VECTOR2I); + register_op<OperatorEvaluatorMul<Vector2i, Vector2i, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR2I, Variant::INT); + register_op<OperatorEvaluatorMul<Vector2i, Vector2i, double>>(Variant::OP_MULTIPLY, Variant::VECTOR2I, Variant::FLOAT); + + register_op<OperatorEvaluatorMul<Vector3, Vector3, Vector3>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::VECTOR3); + register_op<OperatorEvaluatorMul<Vector3, Vector3, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::INT); + register_op<OperatorEvaluatorMul<Vector3, Vector3, double>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::FLOAT); + + register_op<OperatorEvaluatorMul<Vector3i, Vector3i, Vector3i>>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorMul<Vector3i, Vector3i, int64_t>>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::INT); + register_op<OperatorEvaluatorMul<Vector3i, Vector3i, double>>(Variant::OP_MULTIPLY, Variant::VECTOR3I, Variant::FLOAT); + + register_op<OperatorEvaluatorMul<Quat, Quat, Quat>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::QUAT); + register_op<OperatorEvaluatorMul<Quat, Quat, int64_t>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::INT); + register_op<OperatorEvaluatorMul<Quat, Quat, double>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::FLOAT); + + register_op<OperatorEvaluatorMul<Color, Color, Color>>(Variant::OP_MULTIPLY, Variant::COLOR, Variant::COLOR); + register_op<OperatorEvaluatorMul<Color, Color, int64_t>>(Variant::OP_MULTIPLY, Variant::COLOR, Variant::INT); + register_op<OperatorEvaluatorMul<Color, Color, double>>(Variant::OP_MULTIPLY, Variant::COLOR, Variant::FLOAT); + + register_op<OperatorEvaluatorMul<Transform2D, Transform2D, Transform2D>>(Variant::OP_MULTIPLY, Variant::TRANSFORM2D, Variant::TRANSFORM2D); + register_op<OperatorEvaluatorXForm<Vector2, Transform2D, Vector2>>(Variant::OP_MULTIPLY, Variant::TRANSFORM2D, Variant::VECTOR2); + register_op<OperatorEvaluatorXFormInv<Vector2, Vector2, Transform2D>>(Variant::OP_MULTIPLY, Variant::VECTOR2, Variant::TRANSFORM2D); + register_op<OperatorEvaluatorXForm<Rect2, Transform2D, Rect2>>(Variant::OP_MULTIPLY, Variant::TRANSFORM2D, Variant::RECT2); + register_op<OperatorEvaluatorXFormInv<Rect2, Rect2, Transform2D>>(Variant::OP_MULTIPLY, Variant::RECT2, Variant::TRANSFORM2D); + register_op<OperatorEvaluatorXForm<Vector<Vector2>, Transform2D, Vector<Vector2>>>(Variant::OP_MULTIPLY, Variant::TRANSFORM2D, Variant::PACKED_VECTOR2_ARRAY); + register_op<OperatorEvaluatorXFormInv<Vector<Vector2>, Vector<Vector2>, Transform2D>>(Variant::OP_MULTIPLY, Variant::PACKED_VECTOR2_ARRAY, Variant::TRANSFORM2D); + + register_op<OperatorEvaluatorMul<Transform, Transform, Transform>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::TRANSFORM); + register_op<OperatorEvaluatorXForm<Vector3, Transform, Vector3>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::VECTOR3); + register_op<OperatorEvaluatorXFormInv<Vector3, Vector3, Transform>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::TRANSFORM); + register_op<OperatorEvaluatorXForm<::AABB, Transform, ::AABB>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::AABB); + register_op<OperatorEvaluatorXFormInv<::AABB, ::AABB, Transform>>(Variant::OP_MULTIPLY, Variant::AABB, Variant::TRANSFORM); + register_op<OperatorEvaluatorXForm<Vector<Vector3>, Transform, Vector<Vector3>>>(Variant::OP_MULTIPLY, Variant::TRANSFORM, Variant::PACKED_VECTOR3_ARRAY); + register_op<OperatorEvaluatorXFormInv<Vector<Vector3>, Vector<Vector3>, Transform>>(Variant::OP_MULTIPLY, Variant::PACKED_VECTOR3_ARRAY, Variant::TRANSFORM); + + register_op<OperatorEvaluatorMul<Basis, Basis, Basis>>(Variant::OP_MULTIPLY, Variant::BASIS, Variant::BASIS); + register_op<OperatorEvaluatorXForm<Vector3, Basis, Vector3>>(Variant::OP_MULTIPLY, Variant::BASIS, Variant::VECTOR3); + register_op<OperatorEvaluatorXFormInv<Vector3, Vector3, Basis>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::BASIS); + + register_op<OperatorEvaluatorMul<Quat, Quat, Quat>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::QUAT); + register_op<OperatorEvaluatorMul<Quat, Quat, int64_t>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::INT); + register_op<OperatorEvaluatorMul<Quat, int64_t, Quat>>(Variant::OP_MULTIPLY, Variant::INT, Variant::QUAT); + register_op<OperatorEvaluatorMul<Quat, Quat, double>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::FLOAT); + register_op<OperatorEvaluatorMul<Quat, double, Quat>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::QUAT); + register_op<OperatorEvaluatorXForm<Vector3, Quat, Vector3>>(Variant::OP_MULTIPLY, Variant::QUAT, Variant::VECTOR3); + register_op<OperatorEvaluatorXFormInv<Vector3, Vector3, Quat>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::QUAT); + + register_op<OperatorEvaluatorMul<Color, Color, Color>>(Variant::OP_MULTIPLY, Variant::COLOR, Variant::COLOR); + register_op<OperatorEvaluatorMul<Color, Color, int64_t>>(Variant::OP_MULTIPLY, Variant::COLOR, Variant::INT); + register_op<OperatorEvaluatorMul<Color, int64_t, Color>>(Variant::OP_MULTIPLY, Variant::INT, Variant::COLOR); + register_op<OperatorEvaluatorMul<Color, Color, double>>(Variant::OP_MULTIPLY, Variant::COLOR, Variant::FLOAT); + register_op<OperatorEvaluatorMul<Color, double, Color>>(Variant::OP_MULTIPLY, Variant::FLOAT, Variant::COLOR); + + register_op<OperatorEvaluatorDivNZ<int64_t, int64_t, int64_t>>(Variant::OP_DIVIDE, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorDiv<double, double, int64_t>>(Variant::OP_DIVIDE, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorDiv<double, int64_t, double>>(Variant::OP_DIVIDE, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorDiv<double, double, double>>(Variant::OP_DIVIDE, Variant::FLOAT, Variant::FLOAT); + + register_op<OperatorEvaluatorDiv<Vector2, Vector2, Vector2>>(Variant::OP_DIVIDE, Variant::VECTOR2, Variant::VECTOR2); + register_op<OperatorEvaluatorDiv<Vector2, Vector2, double>>(Variant::OP_DIVIDE, Variant::VECTOR2, Variant::FLOAT); + register_op<OperatorEvaluatorDiv<Vector2, Vector2, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR2, Variant::INT); + + register_op<OperatorEvaluatorDiv<Vector2i, Vector2i, Vector2i>>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::VECTOR2I); + register_op<OperatorEvaluatorDivNZ<Vector2i, Vector2i, double>>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::FLOAT); + register_op<OperatorEvaluatorDivNZ<Vector2i, Vector2i, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR2I, Variant::INT); + + register_op<OperatorEvaluatorDiv<Vector2, Vector2, Vector2>>(Variant::OP_DIVIDE, Variant::VECTOR2, Variant::VECTOR2); + register_op<OperatorEvaluatorDiv<Vector2, Vector2, double>>(Variant::OP_DIVIDE, Variant::VECTOR2, Variant::FLOAT); + register_op<OperatorEvaluatorDiv<Vector2, Vector2, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR2, Variant::INT); + + register_op<OperatorEvaluatorDiv<Vector3, Vector3, Vector3>>(Variant::OP_DIVIDE, Variant::VECTOR3, Variant::VECTOR3); + register_op<OperatorEvaluatorDiv<Vector3, Vector3, double>>(Variant::OP_DIVIDE, Variant::VECTOR3, Variant::FLOAT); + register_op<OperatorEvaluatorDiv<Vector3, Vector3, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR3, Variant::INT); + + register_op<OperatorEvaluatorDiv<Vector3i, Vector3i, Vector3i>>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorDivNZ<Vector3i, Vector3i, double>>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::FLOAT); + register_op<OperatorEvaluatorDivNZ<Vector3i, Vector3i, int64_t>>(Variant::OP_DIVIDE, Variant::VECTOR3I, Variant::INT); + + register_op<OperatorEvaluatorDiv<Quat, Quat, double>>(Variant::OP_DIVIDE, Variant::QUAT, Variant::FLOAT); + register_op<OperatorEvaluatorDiv<Quat, Quat, int64_t>>(Variant::OP_DIVIDE, Variant::QUAT, Variant::INT); + + register_op<OperatorEvaluatorDiv<Color, Color, Color>>(Variant::OP_DIVIDE, Variant::COLOR, Variant::COLOR); + register_op<OperatorEvaluatorDiv<Color, Color, double>>(Variant::OP_DIVIDE, Variant::COLOR, Variant::FLOAT); + register_op<OperatorEvaluatorDiv<Color, Color, int64_t>>(Variant::OP_DIVIDE, Variant::COLOR, Variant::INT); + + register_op<OperatorEvaluatorModNZ<int64_t, int64_t, int64_t>>(Variant::OP_MODULE, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorMod<Vector2i, Vector2i, Vector2i>>(Variant::OP_MODULE, Variant::VECTOR2I, Variant::VECTOR2I); + register_op<OperatorEvaluatorModNZ<Vector2i, Vector2i, int64_t>>(Variant::OP_MODULE, Variant::VECTOR2I, Variant::INT); + + register_op<OperatorEvaluatorMod<Vector3i, Vector3i, Vector3i>>(Variant::OP_MODULE, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorModNZ<Vector3i, Vector3i, int64_t>>(Variant::OP_MODULE, Variant::VECTOR3I, Variant::INT); + + register_op<OperatorEvaluatorStringModNil>(Variant::OP_MODULE, Variant::STRING, Variant::NIL); + + register_op<OperatorEvaluatorStringModT<bool>>(Variant::OP_MODULE, Variant::STRING, Variant::BOOL); + register_op<OperatorEvaluatorStringModT<int64_t>>(Variant::OP_MODULE, Variant::STRING, Variant::INT); + register_op<OperatorEvaluatorStringModT<double>>(Variant::OP_MODULE, Variant::STRING, Variant::FLOAT); + register_op<OperatorEvaluatorStringModT<String>>(Variant::OP_MODULE, Variant::STRING, Variant::STRING); + register_op<OperatorEvaluatorStringModT<Vector2>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR2); + register_op<OperatorEvaluatorStringModT<Vector2i>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR2I); + register_op<OperatorEvaluatorStringModT<Rect2>>(Variant::OP_MODULE, Variant::STRING, Variant::RECT2); + register_op<OperatorEvaluatorStringModT<Rect2i>>(Variant::OP_MODULE, Variant::STRING, Variant::RECT2I); + register_op<OperatorEvaluatorStringModT<Vector3>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR3); + register_op<OperatorEvaluatorStringModT<Vector3i>>(Variant::OP_MODULE, Variant::STRING, Variant::VECTOR3I); + register_op<OperatorEvaluatorStringModT<Transform2D>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM2D); + register_op<OperatorEvaluatorStringModT<Plane>>(Variant::OP_MODULE, Variant::STRING, Variant::PLANE); + register_op<OperatorEvaluatorStringModT<Quat>>(Variant::OP_MODULE, Variant::STRING, Variant::QUAT); + register_op<OperatorEvaluatorStringModT<::AABB>>(Variant::OP_MODULE, Variant::STRING, Variant::AABB); + register_op<OperatorEvaluatorStringModT<Basis>>(Variant::OP_MODULE, Variant::STRING, Variant::BASIS); + register_op<OperatorEvaluatorStringModT<Transform>>(Variant::OP_MODULE, Variant::STRING, Variant::TRANSFORM); + + register_op<OperatorEvaluatorStringModT<Color>>(Variant::OP_MODULE, Variant::STRING, Variant::COLOR); + register_op<OperatorEvaluatorStringModT<StringName>>(Variant::OP_MODULE, Variant::STRING, Variant::STRING_NAME); + register_op<OperatorEvaluatorStringModT<NodePath>>(Variant::OP_MODULE, Variant::STRING, Variant::NODE_PATH); + register_op<OperatorEvaluatorStringModObject>(Variant::OP_MODULE, Variant::STRING, Variant::OBJECT); + register_op<OperatorEvaluatorStringModT<Callable>>(Variant::OP_MODULE, Variant::STRING, Variant::CALLABLE); + register_op<OperatorEvaluatorStringModT<Signal>>(Variant::OP_MODULE, Variant::STRING, Variant::SIGNAL); + register_op<OperatorEvaluatorStringModT<Dictionary>>(Variant::OP_MODULE, Variant::STRING, Variant::DICTIONARY); + register_op<OperatorEvaluatorStringModArray>(Variant::OP_MODULE, Variant::STRING, Variant::ARRAY); + + register_op<OperatorEvaluatorStringModT<PackedByteArray>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_BYTE_ARRAY); + register_op<OperatorEvaluatorStringModT<PackedInt32Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_INT32_ARRAY); + register_op<OperatorEvaluatorStringModT<PackedInt64Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_INT64_ARRAY); + register_op<OperatorEvaluatorStringModT<PackedFloat32Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_FLOAT32_ARRAY); + register_op<OperatorEvaluatorStringModT<PackedFloat64Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_FLOAT64_ARRAY); + register_op<OperatorEvaluatorStringModT<PackedStringArray>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_STRING_ARRAY); + register_op<OperatorEvaluatorStringModT<PackedVector2Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_VECTOR2_ARRAY); + register_op<OperatorEvaluatorStringModT<PackedVector3Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_VECTOR3_ARRAY); + register_op<OperatorEvaluatorStringModT<PackedColorArray>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_COLOR_ARRAY); + + register_op<OperatorEvaluatorNeg<int64_t, int64_t>>(Variant::OP_NEGATE, Variant::INT, Variant::NIL); + register_op<OperatorEvaluatorNeg<double, double>>(Variant::OP_NEGATE, Variant::FLOAT, Variant::NIL); + register_op<OperatorEvaluatorNeg<Vector2, Vector2>>(Variant::OP_NEGATE, Variant::VECTOR2, Variant::NIL); + register_op<OperatorEvaluatorNeg<Vector2i, Vector2i>>(Variant::OP_NEGATE, Variant::VECTOR2I, Variant::NIL); + register_op<OperatorEvaluatorNeg<Vector3, Vector3>>(Variant::OP_NEGATE, Variant::VECTOR3, Variant::NIL); + register_op<OperatorEvaluatorNeg<Vector3i, Vector3i>>(Variant::OP_NEGATE, Variant::VECTOR3I, Variant::NIL); + register_op<OperatorEvaluatorNeg<Quat, Quat>>(Variant::OP_NEGATE, Variant::QUAT, Variant::NIL); + register_op<OperatorEvaluatorNeg<Plane, Plane>>(Variant::OP_NEGATE, Variant::PLANE, Variant::NIL); + register_op<OperatorEvaluatorNeg<Color, Color>>(Variant::OP_NEGATE, Variant::COLOR, Variant::NIL); + + register_op<OperatorEvaluatorPos<int64_t, int64_t>>(Variant::OP_POSITIVE, Variant::INT, Variant::NIL); + register_op<OperatorEvaluatorPos<double, double>>(Variant::OP_POSITIVE, Variant::FLOAT, Variant::NIL); + register_op<OperatorEvaluatorPos<Vector2, Vector2>>(Variant::OP_POSITIVE, Variant::VECTOR2, Variant::NIL); + register_op<OperatorEvaluatorPos<Vector2i, Vector2i>>(Variant::OP_POSITIVE, Variant::VECTOR2I, Variant::NIL); + register_op<OperatorEvaluatorPos<Vector3, Vector3>>(Variant::OP_POSITIVE, Variant::VECTOR3, Variant::NIL); + register_op<OperatorEvaluatorPos<Vector3i, Vector3i>>(Variant::OP_POSITIVE, Variant::VECTOR3I, Variant::NIL); + register_op<OperatorEvaluatorPos<Quat, Quat>>(Variant::OP_POSITIVE, Variant::QUAT, Variant::NIL); + register_op<OperatorEvaluatorPos<Plane, Plane>>(Variant::OP_POSITIVE, Variant::PLANE, Variant::NIL); + register_op<OperatorEvaluatorPos<Color, Color>>(Variant::OP_POSITIVE, Variant::COLOR, Variant::NIL); + + register_op<OperatorEvaluatorShiftLeft<int64_t, int64_t, int64_t>>(Variant::OP_SHIFT_LEFT, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorShiftRight<int64_t, int64_t, int64_t>>(Variant::OP_SHIFT_RIGHT, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorBitOr<int64_t, int64_t, int64_t>>(Variant::OP_BIT_OR, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorBitAnd<int64_t, int64_t, int64_t>>(Variant::OP_BIT_AND, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorBitXor<int64_t, int64_t, int64_t>>(Variant::OP_BIT_XOR, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorBitNeg<int64_t, int64_t>>(Variant::OP_BIT_NEGATE, Variant::INT, Variant::NIL); + + register_op<OperatorEvaluatorBitNeg<int64_t, int64_t>>(Variant::OP_BIT_NEGATE, Variant::INT, Variant::NIL); + + register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_EQUAL, Variant::NIL, Variant::NIL>>(Variant::OP_EQUAL, Variant::NIL, Variant::NIL); + register_op<OperatorEvaluatorEqual<bool, bool>>(Variant::OP_EQUAL, Variant::BOOL, Variant::BOOL); + register_op<OperatorEvaluatorEqual<int64_t, int64_t>>(Variant::OP_EQUAL, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorEqual<int64_t, double>>(Variant::OP_EQUAL, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorEqual<double, int64_t>>(Variant::OP_EQUAL, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorEqual<double, double>>(Variant::OP_EQUAL, Variant::FLOAT, Variant::FLOAT); + register_op<OperatorEvaluatorEqual<String, String>>(Variant::OP_EQUAL, Variant::STRING, Variant::STRING); + register_op<OperatorEvaluatorEqual<Vector2, Vector2>>(Variant::OP_EQUAL, Variant::VECTOR2, Variant::VECTOR2); + register_op<OperatorEvaluatorEqual<Vector2i, Vector2i>>(Variant::OP_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I); + register_op<OperatorEvaluatorEqual<Rect2, Rect2>>(Variant::OP_EQUAL, Variant::RECT2, Variant::RECT2); + register_op<OperatorEvaluatorEqual<Rect2i, Rect2i>>(Variant::OP_EQUAL, Variant::RECT2I, Variant::RECT2I); + register_op<OperatorEvaluatorEqual<Vector3, Vector3>>(Variant::OP_EQUAL, Variant::VECTOR3, Variant::VECTOR3); + register_op<OperatorEvaluatorEqual<Vector3i, Vector3i>>(Variant::OP_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorEqual<Transform2D, Transform2D>>(Variant::OP_EQUAL, Variant::TRANSFORM2D, Variant::TRANSFORM2D); + register_op<OperatorEvaluatorEqual<Plane, Plane>>(Variant::OP_EQUAL, Variant::PLANE, Variant::PLANE); + register_op<OperatorEvaluatorEqual<Quat, Quat>>(Variant::OP_EQUAL, Variant::QUAT, Variant::QUAT); + register_op<OperatorEvaluatorEqual<::AABB, ::AABB>>(Variant::OP_EQUAL, Variant::AABB, Variant::AABB); + register_op<OperatorEvaluatorEqual<Basis, Basis>>(Variant::OP_EQUAL, Variant::BASIS, Variant::BASIS); + register_op<OperatorEvaluatorEqual<Transform, Transform>>(Variant::OP_EQUAL, Variant::TRANSFORM, Variant::TRANSFORM); + register_op<OperatorEvaluatorEqual<Color, Color>>(Variant::OP_EQUAL, Variant::COLOR, Variant::COLOR); + + register_op<OperatorEvaluatorEqual<StringName, String>>(Variant::OP_EQUAL, Variant::STRING_NAME, Variant::STRING); + register_op<OperatorEvaluatorEqual<String, StringName>>(Variant::OP_EQUAL, Variant::STRING, Variant::STRING_NAME); + register_op<OperatorEvaluatorEqual<StringName, StringName>>(Variant::OP_EQUAL, Variant::STRING_NAME, Variant::STRING_NAME); + + register_op<OperatorEvaluatorEqual<NodePath, NodePath>>(Variant::OP_EQUAL, Variant::NODE_PATH, Variant::NODE_PATH); + register_op<OperatorEvaluatorEqual<::RID, ::RID>>(Variant::OP_EQUAL, Variant::RID, Variant::RID); + + register_op<OperatorEvaluatorEqualObject>(Variant::OP_EQUAL, Variant::OBJECT, Variant::OBJECT); + register_op<OperatorEvaluatorEqualObjectNil>(Variant::OP_EQUAL, Variant::OBJECT, Variant::NIL); + register_op<OperatorEvaluatorEqualNilObject>(Variant::OP_EQUAL, Variant::NIL, Variant::OBJECT); + + register_op<OperatorEvaluatorEqual<Callable, Callable>>(Variant::OP_EQUAL, Variant::CALLABLE, Variant::CALLABLE); + register_op<OperatorEvaluatorEqual<Signal, Signal>>(Variant::OP_EQUAL, Variant::SIGNAL, Variant::SIGNAL); + register_op<OperatorEvaluatorEqual<Dictionary, Dictionary>>(Variant::OP_EQUAL, Variant::DICTIONARY, Variant::DICTIONARY); + register_op<OperatorEvaluatorEqual<Array, Array>>(Variant::OP_EQUAL, Variant::ARRAY, Variant::ARRAY); + register_op<OperatorEvaluatorEqual<PackedByteArray, PackedByteArray>>(Variant::OP_EQUAL, Variant::PACKED_BYTE_ARRAY, Variant::PACKED_BYTE_ARRAY); + register_op<OperatorEvaluatorEqual<PackedInt32Array, PackedInt32Array>>(Variant::OP_EQUAL, Variant::PACKED_INT32_ARRAY, Variant::PACKED_INT32_ARRAY); + register_op<OperatorEvaluatorEqual<PackedInt64Array, PackedInt64Array>>(Variant::OP_EQUAL, Variant::PACKED_INT64_ARRAY, Variant::PACKED_INT64_ARRAY); + register_op<OperatorEvaluatorEqual<PackedFloat32Array, PackedFloat32Array>>(Variant::OP_EQUAL, Variant::PACKED_FLOAT32_ARRAY, Variant::PACKED_FLOAT32_ARRAY); + register_op<OperatorEvaluatorEqual<PackedFloat64Array, PackedFloat64Array>>(Variant::OP_EQUAL, Variant::PACKED_FLOAT64_ARRAY, Variant::PACKED_FLOAT64_ARRAY); + register_op<OperatorEvaluatorEqual<PackedStringArray, PackedStringArray>>(Variant::OP_EQUAL, Variant::PACKED_STRING_ARRAY, Variant::PACKED_STRING_ARRAY); + register_op<OperatorEvaluatorEqual<PackedVector2Array, PackedVector2Array>>(Variant::OP_EQUAL, Variant::PACKED_VECTOR2_ARRAY, Variant::PACKED_VECTOR2_ARRAY); + register_op<OperatorEvaluatorEqual<PackedVector3Array, PackedVector3Array>>(Variant::OP_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::PACKED_VECTOR3_ARRAY); + register_op<OperatorEvaluatorEqual<PackedColorArray, PackedColorArray>>(Variant::OP_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::PACKED_COLOR_ARRAY); + + register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_NOT_EQUAL, Variant::NIL, Variant::NIL>>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::NIL); + register_op<OperatorEvaluatorNotEqual<bool, bool>>(Variant::OP_NOT_EQUAL, Variant::BOOL, Variant::BOOL); + register_op<OperatorEvaluatorNotEqual<int64_t, int64_t>>(Variant::OP_NOT_EQUAL, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorNotEqual<int64_t, double>>(Variant::OP_NOT_EQUAL, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorNotEqual<double, int64_t>>(Variant::OP_NOT_EQUAL, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorNotEqual<double, double>>(Variant::OP_NOT_EQUAL, Variant::FLOAT, Variant::FLOAT); + register_op<OperatorEvaluatorNotEqual<String, String>>(Variant::OP_NOT_EQUAL, Variant::STRING, Variant::STRING); + register_op<OperatorEvaluatorNotEqual<Vector2, Vector2>>(Variant::OP_NOT_EQUAL, Variant::VECTOR2, Variant::VECTOR2); + register_op<OperatorEvaluatorNotEqual<Vector2i, Vector2i>>(Variant::OP_NOT_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I); + register_op<OperatorEvaluatorNotEqual<Rect2, Rect2>>(Variant::OP_NOT_EQUAL, Variant::RECT2, Variant::RECT2); + register_op<OperatorEvaluatorNotEqual<Rect2i, Rect2i>>(Variant::OP_NOT_EQUAL, Variant::RECT2I, Variant::RECT2I); + register_op<OperatorEvaluatorNotEqual<Vector3, Vector3>>(Variant::OP_NOT_EQUAL, Variant::VECTOR3, Variant::VECTOR3); + register_op<OperatorEvaluatorNotEqual<Vector3i, Vector3i>>(Variant::OP_NOT_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorNotEqual<Transform2D, Transform2D>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM2D, Variant::TRANSFORM2D); + register_op<OperatorEvaluatorNotEqual<Plane, Plane>>(Variant::OP_NOT_EQUAL, Variant::PLANE, Variant::PLANE); + register_op<OperatorEvaluatorNotEqual<Quat, Quat>>(Variant::OP_NOT_EQUAL, Variant::QUAT, Variant::QUAT); + register_op<OperatorEvaluatorNotEqual<::AABB, ::AABB>>(Variant::OP_NOT_EQUAL, Variant::AABB, Variant::AABB); + register_op<OperatorEvaluatorNotEqual<Basis, Basis>>(Variant::OP_NOT_EQUAL, Variant::BASIS, Variant::BASIS); + register_op<OperatorEvaluatorNotEqual<Transform, Transform>>(Variant::OP_NOT_EQUAL, Variant::TRANSFORM, Variant::TRANSFORM); + register_op<OperatorEvaluatorNotEqual<Color, Color>>(Variant::OP_NOT_EQUAL, Variant::COLOR, Variant::COLOR); + + register_op<OperatorEvaluatorNotEqual<StringName, String>>(Variant::OP_NOT_EQUAL, Variant::STRING_NAME, Variant::STRING); + register_op<OperatorEvaluatorNotEqual<String, StringName>>(Variant::OP_NOT_EQUAL, Variant::STRING, Variant::STRING_NAME); + register_op<OperatorEvaluatorNotEqual<StringName, StringName>>(Variant::OP_NOT_EQUAL, Variant::STRING_NAME, Variant::STRING_NAME); + + register_op<OperatorEvaluatorNotEqual<NodePath, NodePath>>(Variant::OP_NOT_EQUAL, Variant::NODE_PATH, Variant::NODE_PATH); + register_op<OperatorEvaluatorNotEqual<::RID, ::RID>>(Variant::OP_NOT_EQUAL, Variant::RID, Variant::RID); + + register_op<OperatorEvaluatorNotEqualObject>(Variant::OP_NOT_EQUAL, Variant::OBJECT, Variant::OBJECT); + register_op<OperatorEvaluatorNotEqualObjectNil>(Variant::OP_NOT_EQUAL, Variant::OBJECT, Variant::NIL); + register_op<OperatorEvaluatorNotEqualNilObject>(Variant::OP_NOT_EQUAL, Variant::NIL, Variant::OBJECT); + + register_op<OperatorEvaluatorNotEqual<Callable, Callable>>(Variant::OP_NOT_EQUAL, Variant::CALLABLE, Variant::CALLABLE); + register_op<OperatorEvaluatorNotEqual<Signal, Signal>>(Variant::OP_NOT_EQUAL, Variant::SIGNAL, Variant::SIGNAL); + register_op<OperatorEvaluatorNotEqual<Dictionary, Dictionary>>(Variant::OP_NOT_EQUAL, Variant::DICTIONARY, Variant::DICTIONARY); + register_op<OperatorEvaluatorNotEqual<Array, Array>>(Variant::OP_NOT_EQUAL, Variant::ARRAY, Variant::ARRAY); + register_op<OperatorEvaluatorNotEqual<PackedByteArray, PackedByteArray>>(Variant::OP_NOT_EQUAL, Variant::PACKED_BYTE_ARRAY, Variant::PACKED_BYTE_ARRAY); + register_op<OperatorEvaluatorNotEqual<PackedInt32Array, PackedInt32Array>>(Variant::OP_NOT_EQUAL, Variant::PACKED_INT32_ARRAY, Variant::PACKED_INT32_ARRAY); + register_op<OperatorEvaluatorNotEqual<PackedInt64Array, PackedInt64Array>>(Variant::OP_NOT_EQUAL, Variant::PACKED_INT64_ARRAY, Variant::PACKED_INT64_ARRAY); + register_op<OperatorEvaluatorNotEqual<PackedFloat32Array, PackedFloat32Array>>(Variant::OP_NOT_EQUAL, Variant::PACKED_FLOAT32_ARRAY, Variant::PACKED_FLOAT32_ARRAY); + register_op<OperatorEvaluatorNotEqual<PackedFloat64Array, PackedFloat64Array>>(Variant::OP_NOT_EQUAL, Variant::PACKED_FLOAT64_ARRAY, Variant::PACKED_FLOAT64_ARRAY); + register_op<OperatorEvaluatorNotEqual<PackedStringArray, PackedStringArray>>(Variant::OP_NOT_EQUAL, Variant::PACKED_STRING_ARRAY, Variant::PACKED_STRING_ARRAY); + register_op<OperatorEvaluatorNotEqual<PackedVector2Array, PackedVector2Array>>(Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR2_ARRAY, Variant::PACKED_VECTOR2_ARRAY); + register_op<OperatorEvaluatorNotEqual<PackedVector3Array, PackedVector3Array>>(Variant::OP_NOT_EQUAL, Variant::PACKED_VECTOR3_ARRAY, Variant::PACKED_VECTOR3_ARRAY); + register_op<OperatorEvaluatorNotEqual<PackedColorArray, PackedColorArray>>(Variant::OP_NOT_EQUAL, Variant::PACKED_COLOR_ARRAY, Variant::PACKED_COLOR_ARRAY); + + register_op<OperatorEvaluatorLess<bool, bool>>(Variant::OP_LESS, Variant::BOOL, Variant::BOOL); + register_op<OperatorEvaluatorLess<int64_t, int64_t>>(Variant::OP_LESS, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorLess<int64_t, double>>(Variant::OP_LESS, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorLess<double, int64_t>>(Variant::OP_LESS, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorLess<double, double>>(Variant::OP_LESS, Variant::FLOAT, Variant::FLOAT); + register_op<OperatorEvaluatorLess<String, String>>(Variant::OP_LESS, Variant::STRING, Variant::STRING); + register_op<OperatorEvaluatorLess<Vector2, Vector2>>(Variant::OP_LESS, Variant::VECTOR2, Variant::VECTOR2); + register_op<OperatorEvaluatorLess<Vector2i, Vector2i>>(Variant::OP_LESS, Variant::VECTOR2I, Variant::VECTOR2I); + register_op<OperatorEvaluatorLess<Vector3, Vector3>>(Variant::OP_LESS, Variant::VECTOR3, Variant::VECTOR3); + register_op<OperatorEvaluatorLess<Vector3i, Vector3i>>(Variant::OP_LESS, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorLess<::RID, ::RID>>(Variant::OP_LESS, Variant::RID, Variant::RID); + register_op<OperatorEvaluatorLess<Array, Array>>(Variant::OP_LESS, Variant::ARRAY, Variant::ARRAY); + + register_op<OperatorEvaluatorLessEqual<int64_t, int64_t>>(Variant::OP_LESS_EQUAL, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorLessEqual<int64_t, double>>(Variant::OP_LESS_EQUAL, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorLessEqual<double, int64_t>>(Variant::OP_LESS_EQUAL, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorLessEqual<double, double>>(Variant::OP_LESS_EQUAL, Variant::FLOAT, Variant::FLOAT); + register_op<OperatorEvaluatorLessEqual<String, String>>(Variant::OP_LESS_EQUAL, Variant::STRING, Variant::STRING); + register_op<OperatorEvaluatorLessEqual<Vector2, Vector2>>(Variant::OP_LESS_EQUAL, Variant::VECTOR2, Variant::VECTOR2); + register_op<OperatorEvaluatorLessEqual<Vector2i, Vector2i>>(Variant::OP_LESS_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I); + register_op<OperatorEvaluatorLessEqual<Vector3, Vector3>>(Variant::OP_LESS_EQUAL, Variant::VECTOR3, Variant::VECTOR3); + register_op<OperatorEvaluatorLessEqual<Vector3i, Vector3i>>(Variant::OP_LESS_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorLessEqual<::RID, ::RID>>(Variant::OP_LESS_EQUAL, Variant::RID, Variant::RID); + register_op<OperatorEvaluatorLessEqual<Array, Array>>(Variant::OP_LESS_EQUAL, Variant::ARRAY, Variant::ARRAY); + + register_op<OperatorEvaluatorGreater<bool, bool>>(Variant::OP_GREATER, Variant::BOOL, Variant::BOOL); + register_op<OperatorEvaluatorGreater<int64_t, int64_t>>(Variant::OP_GREATER, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorGreater<int64_t, double>>(Variant::OP_GREATER, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorGreater<double, int64_t>>(Variant::OP_GREATER, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorGreater<double, double>>(Variant::OP_GREATER, Variant::FLOAT, Variant::FLOAT); + register_op<OperatorEvaluatorGreater<String, String>>(Variant::OP_GREATER, Variant::STRING, Variant::STRING); + register_op<OperatorEvaluatorGreater<Vector2, Vector2>>(Variant::OP_GREATER, Variant::VECTOR2, Variant::VECTOR2); + register_op<OperatorEvaluatorGreater<Vector2i, Vector2i>>(Variant::OP_GREATER, Variant::VECTOR2I, Variant::VECTOR2I); + register_op<OperatorEvaluatorGreater<Vector3, Vector3>>(Variant::OP_GREATER, Variant::VECTOR3, Variant::VECTOR3); + register_op<OperatorEvaluatorGreater<Vector3i, Vector3i>>(Variant::OP_GREATER, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorGreater<::RID, ::RID>>(Variant::OP_GREATER, Variant::RID, Variant::RID); + register_op<OperatorEvaluatorGreater<Array, Array>>(Variant::OP_GREATER, Variant::ARRAY, Variant::ARRAY); + + register_op<OperatorEvaluatorGreaterEqual<int64_t, int64_t>>(Variant::OP_GREATER_EQUAL, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorGreaterEqual<int64_t, double>>(Variant::OP_GREATER_EQUAL, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorGreaterEqual<double, int64_t>>(Variant::OP_GREATER_EQUAL, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorGreaterEqual<double, double>>(Variant::OP_GREATER_EQUAL, Variant::FLOAT, Variant::FLOAT); + register_op<OperatorEvaluatorGreaterEqual<String, String>>(Variant::OP_GREATER_EQUAL, Variant::STRING, Variant::STRING); + register_op<OperatorEvaluatorGreaterEqual<Vector2, Vector2>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR2, Variant::VECTOR2); + register_op<OperatorEvaluatorGreaterEqual<Vector2i, Vector2i>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR2I, Variant::VECTOR2I); + register_op<OperatorEvaluatorGreaterEqual<Vector3, Vector3>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR3, Variant::VECTOR3); + register_op<OperatorEvaluatorGreaterEqual<Vector3i, Vector3i>>(Variant::OP_GREATER_EQUAL, Variant::VECTOR3I, Variant::VECTOR3I); + register_op<OperatorEvaluatorGreaterEqual<::RID, ::RID>>(Variant::OP_GREATER_EQUAL, Variant::RID, Variant::RID); + register_op<OperatorEvaluatorGreaterEqual<Array, Array>>(Variant::OP_GREATER_EQUAL, Variant::ARRAY, Variant::ARRAY); + + register_op<OperatorEvaluatorAlwaysFalse<Variant::OP_OR, Variant::NIL, Variant::NIL>>(Variant::OP_OR, Variant::NIL, Variant::NIL); + + // OR + register_op<OperatorEvaluatorNilXBoolOr>(Variant::OP_OR, Variant::NIL, Variant::BOOL); + register_op<OperatorEvaluatorBoolXNilOr>(Variant::OP_OR, Variant::BOOL, Variant::NIL); + register_op<OperatorEvaluatorNilXIntOr>(Variant::OP_OR, Variant::NIL, Variant::INT); + register_op<OperatorEvaluatorIntXNilOr>(Variant::OP_OR, Variant::INT, Variant::NIL); + register_op<OperatorEvaluatorNilXFloatOr>(Variant::OP_OR, Variant::NIL, Variant::FLOAT); + register_op<OperatorEvaluatorFloatXNilOr>(Variant::OP_OR, Variant::FLOAT, Variant::NIL); + register_op<OperatorEvaluatorNilXObjectOr>(Variant::OP_OR, Variant::NIL, Variant::OBJECT); + register_op<OperatorEvaluatorObjectXNilOr>(Variant::OP_OR, Variant::OBJECT, Variant::NIL); + + register_op<OperatorEvaluatorBoolXBoolOr>(Variant::OP_OR, Variant::BOOL, Variant::BOOL); + register_op<OperatorEvaluatorBoolXIntOr>(Variant::OP_OR, Variant::BOOL, Variant::INT); + register_op<OperatorEvaluatorIntXBoolOr>(Variant::OP_OR, Variant::INT, Variant::BOOL); + register_op<OperatorEvaluatorBoolXFloatOr>(Variant::OP_OR, Variant::BOOL, Variant::FLOAT); + register_op<OperatorEvaluatorFloatXBoolOr>(Variant::OP_OR, Variant::FLOAT, Variant::BOOL); + register_op<OperatorEvaluatorBoolXObjectOr>(Variant::OP_OR, Variant::BOOL, Variant::OBJECT); + register_op<OperatorEvaluatorObjectXBoolOr>(Variant::OP_OR, Variant::OBJECT, Variant::BOOL); + + register_op<OperatorEvaluatorIntXIntOr>(Variant::OP_OR, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorIntXFloatOr>(Variant::OP_OR, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorFloatXIntOr>(Variant::OP_OR, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorIntXObjectOr>(Variant::OP_OR, Variant::INT, Variant::OBJECT); + register_op<OperatorEvaluatorObjectXIntOr>(Variant::OP_OR, Variant::OBJECT, Variant::INT); + + register_op<OperatorEvaluatorFloatXFloatOr>(Variant::OP_OR, Variant::FLOAT, Variant::FLOAT); + register_op<OperatorEvaluatorFloatXObjectOr>(Variant::OP_OR, Variant::FLOAT, Variant::OBJECT); + register_op<OperatorEvaluatorObjectXFloatOr>(Variant::OP_OR, Variant::OBJECT, Variant::FLOAT); + register_op<OperatorEvaluatorObjectXObjectOr>(Variant::OP_OR, Variant::OBJECT, Variant::OBJECT); + + // AND + register_op<OperatorEvaluatorNilXBoolAnd>(Variant::OP_AND, Variant::NIL, Variant::BOOL); + register_op<OperatorEvaluatorBoolXNilAnd>(Variant::OP_AND, Variant::BOOL, Variant::NIL); + register_op<OperatorEvaluatorNilXIntAnd>(Variant::OP_AND, Variant::NIL, Variant::INT); + register_op<OperatorEvaluatorIntXNilAnd>(Variant::OP_AND, Variant::INT, Variant::NIL); + register_op<OperatorEvaluatorNilXFloatAnd>(Variant::OP_AND, Variant::NIL, Variant::FLOAT); + register_op<OperatorEvaluatorFloatXNilAnd>(Variant::OP_AND, Variant::FLOAT, Variant::NIL); + register_op<OperatorEvaluatorNilXObjectAnd>(Variant::OP_AND, Variant::NIL, Variant::OBJECT); + register_op<OperatorEvaluatorObjectXNilAnd>(Variant::OP_AND, Variant::OBJECT, Variant::NIL); + + register_op<OperatorEvaluatorBoolXBoolAnd>(Variant::OP_AND, Variant::BOOL, Variant::BOOL); + register_op<OperatorEvaluatorBoolXIntAnd>(Variant::OP_AND, Variant::BOOL, Variant::INT); + register_op<OperatorEvaluatorIntXBoolAnd>(Variant::OP_AND, Variant::INT, Variant::BOOL); + register_op<OperatorEvaluatorBoolXFloatAnd>(Variant::OP_AND, Variant::BOOL, Variant::FLOAT); + register_op<OperatorEvaluatorFloatXBoolAnd>(Variant::OP_AND, Variant::FLOAT, Variant::BOOL); + register_op<OperatorEvaluatorBoolXObjectAnd>(Variant::OP_AND, Variant::BOOL, Variant::OBJECT); + register_op<OperatorEvaluatorObjectXBoolAnd>(Variant::OP_AND, Variant::OBJECT, Variant::BOOL); + + register_op<OperatorEvaluatorIntXIntAnd>(Variant::OP_AND, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorIntXFloatAnd>(Variant::OP_AND, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorFloatXIntAnd>(Variant::OP_AND, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorIntXObjectAnd>(Variant::OP_AND, Variant::INT, Variant::OBJECT); + register_op<OperatorEvaluatorObjectXIntAnd>(Variant::OP_AND, Variant::OBJECT, Variant::INT); + + register_op<OperatorEvaluatorFloatXFloatAnd>(Variant::OP_AND, Variant::FLOAT, Variant::FLOAT); + register_op<OperatorEvaluatorFloatXObjectAnd>(Variant::OP_AND, Variant::FLOAT, Variant::OBJECT); + register_op<OperatorEvaluatorObjectXFloatAnd>(Variant::OP_AND, Variant::OBJECT, Variant::FLOAT); + register_op<OperatorEvaluatorObjectXObjectAnd>(Variant::OP_AND, Variant::OBJECT, Variant::OBJECT); + + // XOR + register_op<OperatorEvaluatorNilXBoolXor>(Variant::OP_XOR, Variant::NIL, Variant::BOOL); + register_op<OperatorEvaluatorBoolXNilXor>(Variant::OP_XOR, Variant::BOOL, Variant::NIL); + register_op<OperatorEvaluatorNilXIntXor>(Variant::OP_XOR, Variant::NIL, Variant::INT); + register_op<OperatorEvaluatorIntXNilXor>(Variant::OP_XOR, Variant::INT, Variant::NIL); + register_op<OperatorEvaluatorNilXFloatXor>(Variant::OP_XOR, Variant::NIL, Variant::FLOAT); + register_op<OperatorEvaluatorFloatXNilXor>(Variant::OP_XOR, Variant::FLOAT, Variant::NIL); + register_op<OperatorEvaluatorNilXObjectXor>(Variant::OP_XOR, Variant::NIL, Variant::OBJECT); + register_op<OperatorEvaluatorObjectXNilXor>(Variant::OP_XOR, Variant::OBJECT, Variant::NIL); + + register_op<OperatorEvaluatorBoolXBoolXor>(Variant::OP_XOR, Variant::BOOL, Variant::BOOL); + register_op<OperatorEvaluatorBoolXIntXor>(Variant::OP_XOR, Variant::BOOL, Variant::INT); + register_op<OperatorEvaluatorIntXBoolXor>(Variant::OP_XOR, Variant::INT, Variant::BOOL); + register_op<OperatorEvaluatorBoolXFloatXor>(Variant::OP_XOR, Variant::BOOL, Variant::FLOAT); + register_op<OperatorEvaluatorFloatXBoolXor>(Variant::OP_XOR, Variant::FLOAT, Variant::BOOL); + register_op<OperatorEvaluatorBoolXObjectXor>(Variant::OP_XOR, Variant::BOOL, Variant::OBJECT); + register_op<OperatorEvaluatorObjectXBoolXor>(Variant::OP_XOR, Variant::OBJECT, Variant::BOOL); + + register_op<OperatorEvaluatorIntXIntXor>(Variant::OP_XOR, Variant::INT, Variant::INT); + register_op<OperatorEvaluatorIntXFloatXor>(Variant::OP_XOR, Variant::INT, Variant::FLOAT); + register_op<OperatorEvaluatorFloatXIntXor>(Variant::OP_XOR, Variant::FLOAT, Variant::INT); + register_op<OperatorEvaluatorIntXObjectXor>(Variant::OP_XOR, Variant::INT, Variant::OBJECT); + register_op<OperatorEvaluatorObjectXIntXor>(Variant::OP_XOR, Variant::OBJECT, Variant::INT); + + register_op<OperatorEvaluatorFloatXFloatXor>(Variant::OP_XOR, Variant::FLOAT, Variant::FLOAT); + register_op<OperatorEvaluatorFloatXObjectXor>(Variant::OP_XOR, Variant::FLOAT, Variant::OBJECT); + register_op<OperatorEvaluatorObjectXFloatXor>(Variant::OP_XOR, Variant::OBJECT, Variant::FLOAT); + register_op<OperatorEvaluatorObjectXObjectXor>(Variant::OP_XOR, Variant::OBJECT, Variant::OBJECT); + + register_op<OperatorEvaluatorAlwaysTrue<Variant::OP_NOT, Variant::NIL, Variant::NIL>>(Variant::OP_NOT, Variant::NIL, Variant::NIL); + register_op<OperatorEvaluatorNotBool>(Variant::OP_NOT, Variant::BOOL, Variant::NIL); + register_op<OperatorEvaluatorNotInt>(Variant::OP_NOT, Variant::INT, Variant::NIL); + register_op<OperatorEvaluatorNotFloat>(Variant::OP_NOT, Variant::FLOAT, Variant::NIL); + register_op<OperatorEvaluatorNotObject>(Variant::OP_NOT, Variant::OBJECT, Variant::NIL); + + register_op<OperatorEvaluatorInStringFind>(Variant::OP_IN, Variant::STRING, Variant::STRING); + + register_op<OperatorEvaluatorInDictionaryHasNil>(Variant::OP_IN, Variant::NIL, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<bool>>(Variant::OP_IN, Variant::BOOL, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<int64_t>>(Variant::OP_IN, Variant::INT, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<double>>(Variant::OP_IN, Variant::FLOAT, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<String>>(Variant::OP_IN, Variant::STRING, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Vector2>>(Variant::OP_IN, Variant::VECTOR2, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Vector2i>>(Variant::OP_IN, Variant::VECTOR2I, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Rect2>>(Variant::OP_IN, Variant::RECT2, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Rect2i>>(Variant::OP_IN, Variant::RECT2I, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Vector3>>(Variant::OP_IN, Variant::VECTOR3, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Vector3i>>(Variant::OP_IN, Variant::VECTOR3I, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Transform2D>>(Variant::OP_IN, Variant::TRANSFORM2D, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Plane>>(Variant::OP_IN, Variant::PLANE, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Quat>>(Variant::OP_IN, Variant::QUAT, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<::AABB>>(Variant::OP_IN, Variant::AABB, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Basis>>(Variant::OP_IN, Variant::BASIS, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Transform>>(Variant::OP_IN, Variant::TRANSFORM, Variant::DICTIONARY); + + register_op<OperatorEvaluatorInDictionaryHas<Color>>(Variant::OP_IN, Variant::COLOR, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<StringName>>(Variant::OP_IN, Variant::STRING_NAME, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<NodePath>>(Variant::OP_IN, Variant::NODE_PATH, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHasObject>(Variant::OP_IN, Variant::OBJECT, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Callable>>(Variant::OP_IN, Variant::CALLABLE, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Signal>>(Variant::OP_IN, Variant::SIGNAL, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Dictionary>>(Variant::OP_IN, Variant::DICTIONARY, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<Array>>(Variant::OP_IN, Variant::ARRAY, Variant::DICTIONARY); + + register_op<OperatorEvaluatorInDictionaryHas<PackedByteArray>>(Variant::OP_IN, Variant::PACKED_BYTE_ARRAY, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<PackedInt32Array>>(Variant::OP_IN, Variant::PACKED_INT32_ARRAY, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<PackedInt64Array>>(Variant::OP_IN, Variant::PACKED_INT64_ARRAY, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<PackedFloat32Array>>(Variant::OP_IN, Variant::PACKED_FLOAT32_ARRAY, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<PackedFloat64Array>>(Variant::OP_IN, Variant::PACKED_FLOAT64_ARRAY, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<PackedStringArray>>(Variant::OP_IN, Variant::PACKED_STRING_ARRAY, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<PackedVector2Array>>(Variant::OP_IN, Variant::PACKED_VECTOR2_ARRAY, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<PackedVector3Array>>(Variant::OP_IN, Variant::PACKED_VECTOR3_ARRAY, Variant::DICTIONARY); + register_op<OperatorEvaluatorInDictionaryHas<PackedColorArray>>(Variant::OP_IN, Variant::PACKED_COLOR_ARRAY, Variant::DICTIONARY); + + register_op<OperatorEvaluatorInArrayFindNil>(Variant::OP_IN, Variant::NIL, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<bool, Array>>(Variant::OP_IN, Variant::BOOL, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<int64_t, Array>>(Variant::OP_IN, Variant::INT, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<double, Array>>(Variant::OP_IN, Variant::FLOAT, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<String, Array>>(Variant::OP_IN, Variant::STRING, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Vector2, Array>>(Variant::OP_IN, Variant::VECTOR2, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Vector2i, Array>>(Variant::OP_IN, Variant::VECTOR2I, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Rect2, Array>>(Variant::OP_IN, Variant::RECT2, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Rect2i, Array>>(Variant::OP_IN, Variant::RECT2I, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Vector3, Array>>(Variant::OP_IN, Variant::VECTOR3, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Vector3i, Array>>(Variant::OP_IN, Variant::VECTOR3I, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Transform2D, Array>>(Variant::OP_IN, Variant::TRANSFORM2D, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Plane, Array>>(Variant::OP_IN, Variant::PLANE, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Quat, Array>>(Variant::OP_IN, Variant::QUAT, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<::AABB, Array>>(Variant::OP_IN, Variant::AABB, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Basis, Array>>(Variant::OP_IN, Variant::BASIS, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Transform, Array>>(Variant::OP_IN, Variant::TRANSFORM, Variant::ARRAY); + + register_op<OperatorEvaluatorInArrayFind<Color, Array>>(Variant::OP_IN, Variant::COLOR, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<StringName, Array>>(Variant::OP_IN, Variant::STRING_NAME, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<NodePath, Array>>(Variant::OP_IN, Variant::NODE_PATH, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFindObject>(Variant::OP_IN, Variant::OBJECT, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Callable, Array>>(Variant::OP_IN, Variant::CALLABLE, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Signal, Array>>(Variant::OP_IN, Variant::SIGNAL, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Dictionary, Array>>(Variant::OP_IN, Variant::DICTIONARY, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<Array, Array>>(Variant::OP_IN, Variant::ARRAY, Variant::ARRAY); + + register_op<OperatorEvaluatorInArrayFind<PackedByteArray, Array>>(Variant::OP_IN, Variant::PACKED_BYTE_ARRAY, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<PackedInt32Array, Array>>(Variant::OP_IN, Variant::PACKED_INT32_ARRAY, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<PackedInt64Array, Array>>(Variant::OP_IN, Variant::PACKED_INT64_ARRAY, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<PackedFloat32Array, Array>>(Variant::OP_IN, Variant::PACKED_FLOAT32_ARRAY, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<PackedFloat64Array, Array>>(Variant::OP_IN, Variant::PACKED_FLOAT64_ARRAY, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<PackedStringArray, Array>>(Variant::OP_IN, Variant::PACKED_STRING_ARRAY, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<PackedVector2Array, Array>>(Variant::OP_IN, Variant::PACKED_VECTOR2_ARRAY, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<PackedVector3Array, Array>>(Variant::OP_IN, Variant::PACKED_VECTOR3_ARRAY, Variant::ARRAY); + register_op<OperatorEvaluatorInArrayFind<PackedColorArray, Array>>(Variant::OP_IN, Variant::PACKED_COLOR_ARRAY, Variant::ARRAY); + + register_op<OperatorEvaluatorInArrayFind<int, PackedByteArray>>(Variant::OP_IN, Variant::INT, Variant::PACKED_BYTE_ARRAY); + register_op<OperatorEvaluatorInArrayFind<float, PackedByteArray>>(Variant::OP_IN, Variant::FLOAT, Variant::PACKED_BYTE_ARRAY); + + register_op<OperatorEvaluatorInArrayFind<int, PackedInt32Array>>(Variant::OP_IN, Variant::INT, Variant::PACKED_INT32_ARRAY); + register_op<OperatorEvaluatorInArrayFind<float, PackedInt32Array>>(Variant::OP_IN, Variant::FLOAT, Variant::PACKED_INT32_ARRAY); + + register_op<OperatorEvaluatorInArrayFind<int, PackedInt64Array>>(Variant::OP_IN, Variant::INT, Variant::PACKED_INT64_ARRAY); + register_op<OperatorEvaluatorInArrayFind<float, PackedInt64Array>>(Variant::OP_IN, Variant::FLOAT, Variant::PACKED_INT64_ARRAY); + + register_op<OperatorEvaluatorInArrayFind<int, PackedFloat32Array>>(Variant::OP_IN, Variant::INT, Variant::PACKED_FLOAT32_ARRAY); + register_op<OperatorEvaluatorInArrayFind<float, PackedFloat32Array>>(Variant::OP_IN, Variant::FLOAT, Variant::PACKED_FLOAT32_ARRAY); + + register_op<OperatorEvaluatorInArrayFind<int, PackedFloat64Array>>(Variant::OP_IN, Variant::INT, Variant::PACKED_FLOAT64_ARRAY); + register_op<OperatorEvaluatorInArrayFind<float, PackedFloat64Array>>(Variant::OP_IN, Variant::FLOAT, Variant::PACKED_FLOAT64_ARRAY); + + register_op<OperatorEvaluatorInArrayFind<String, PackedStringArray>>(Variant::OP_IN, Variant::STRING, Variant::PACKED_STRING_ARRAY); + + register_op<OperatorEvaluatorInArrayFind<Vector2, PackedVector2Array>>(Variant::OP_IN, Variant::VECTOR2, Variant::PACKED_VECTOR2_ARRAY); + register_op<OperatorEvaluatorInArrayFind<Vector3, PackedVector3Array>>(Variant::OP_IN, Variant::VECTOR3, Variant::PACKED_VECTOR3_ARRAY); + + register_op<OperatorEvaluatorInArrayFind<Color, PackedColorArray>>(Variant::OP_IN, Variant::COLOR, Variant::PACKED_COLOR_ARRAY); + + register_op<OperatorEvaluatorObjectHasPropertyString>(Variant::OP_IN, Variant::STRING, Variant::OBJECT); + register_op<OperatorEvaluatorObjectHasPropertyStringName>(Variant::OP_IN, Variant::STRING_NAME, Variant::OBJECT); +} + +void Variant::_unregister_variant_operators() { +} + +void Variant::evaluate(const Operator &p_op, const Variant &p_a, + const Variant &p_b, Variant &r_ret, bool &r_valid) { + ERR_FAIL_INDEX(p_op, Variant::OP_MAX); + Variant::Type type_a = p_a.get_type(); + Variant::Type type_b = p_b.get_type(); + ERR_FAIL_INDEX(type_a, Variant::VARIANT_MAX); + ERR_FAIL_INDEX(type_b, Variant::VARIANT_MAX); + + VariantEvaluatorFunction ev = operator_evaluator_table[p_op][type_a][type_b]; + if (unlikely(!ev)) { + r_valid = false; + r_ret = Variant(); + return; + } + + ev(p_a, p_b, &r_ret, r_valid); +} + +Variant::Type Variant::get_operator_return_type(Operator p_operator, Type p_type_a, Type p_type_b) { + ERR_FAIL_INDEX_V(p_operator, Variant::OP_MAX, Variant::NIL); + ERR_FAIL_INDEX_V(p_type_a, Variant::VARIANT_MAX, Variant::NIL); + ERR_FAIL_INDEX_V(p_type_b, Variant::VARIANT_MAX, Variant::NIL); + + return operator_return_type_table[p_operator][p_type_a][p_type_b]; +} + +Variant::ValidatedOperatorEvaluator Variant::get_validated_operator_evaluator(Operator p_operator, Type p_type_a, Type p_type_b) { + ERR_FAIL_INDEX_V(p_operator, Variant::OP_MAX, nullptr); + ERR_FAIL_INDEX_V(p_type_a, Variant::VARIANT_MAX, nullptr); + ERR_FAIL_INDEX_V(p_type_b, Variant::VARIANT_MAX, nullptr); + return validated_operator_evaluator_table[p_operator][p_type_a][p_type_b]; +} + +Variant::PTROperatorEvaluator Variant::get_ptr_operator_evaluator(Operator p_operator, Type p_type_a, Type p_type_b) { + ERR_FAIL_INDEX_V(p_operator, Variant::OP_MAX, nullptr); + ERR_FAIL_INDEX_V(p_type_a, Variant::VARIANT_MAX, nullptr); + ERR_FAIL_INDEX_V(p_type_b, Variant::VARIANT_MAX, nullptr); + return ptr_operator_evaluator_table[p_operator][p_type_a][p_type_b]; +} + +static const char *_op_names[Variant::OP_MAX] = { + "==", + "!=", + "<", + "<=", + ">", + ">=", + "+", + "-", + "*", + "/", + "-", + "+", + "%", + "<<", + ">>", + "&", + "|", + "^", + "~", + "and", + "or", + "xor", + "not", + "in" +}; + +String Variant::get_operator_name(Operator p_op) { + ERR_FAIL_INDEX_V(p_op, OP_MAX, ""); + return _op_names[p_op]; +} + +Variant::operator bool() const { + return booleanize(); +} + +// We consider all uninitialized or empty types to be false based on the type's +// zeroiness. +bool Variant::booleanize() const { + return !is_zero(); +} + +bool Variant::in(const Variant &p_index, bool *r_valid) const { + bool valid; + Variant ret; + evaluate(OP_IN, p_index, *this, ret, valid); + if (r_valid) { + *r_valid = valid; + return false; + } + ERR_FAIL_COND_V(ret.type != BOOL, false); + return *VariantGetInternalPtr<bool>::get_ptr(&ret); +} diff --git a/core/variant_parser.cpp b/core/variant/variant_parser.cpp index 04cd4c1b9b..ed936c626b 100644 --- a/core/variant_parser.cpp +++ b/core/variant/variant_parser.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +33,7 @@ #include "core/input/input_event.h" #include "core/io/resource_loader.h" #include "core/os/keyboard.h" -#include "core/string_buffer.h" +#include "core/string/string_buffer.h" char32_t VariantParser::StreamFile::get_char() { return f->get_8(); @@ -743,6 +743,8 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return ERR_PARSE_ERROR; } + REF ref = REF(Object::cast_to<Reference>(obj)); + get_token(p_stream, token, line, r_err_str); if (token.type != TK_COMMA) { r_err_str = "Expected ',' after object type"; @@ -767,12 +769,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, } if (token2.type == TK_PARENTHESIS_CLOSE) { - Reference *reference = Object::cast_to<Reference>(obj); - if (reference) { - value = REF(reference); - } else { - value = obj; - } + value = ref.is_valid() ? Variant(ref) : Variant(obj); return OK; } diff --git a/core/variant_parser.h b/core/variant/variant_parser.h index 12329e2db6..5703f0200c 100644 --- a/core/variant_parser.h +++ b/core/variant/variant_parser.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,9 +31,9 @@ #ifndef VARIANT_PARSER_H #define VARIANT_PARSER_H +#include "core/io/resource.h" #include "core/os/file_access.h" -#include "core/resource.h" -#include "core/variant.h" +#include "core/variant/variant.h" class VariantParser { public: @@ -100,7 +100,6 @@ public: }; enum Expecting { - EXPECT_OBJECT, EXPECT_OBJECT_KEY, EXPECT_COLON, diff --git a/core/variant/variant_setget.cpp b/core/variant/variant_setget.cpp new file mode 100644 index 0000000000..ea8263402a --- /dev/null +++ b/core/variant/variant_setget.cpp @@ -0,0 +1,2524 @@ +/*************************************************************************/ +/* variant_setget.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "variant.h" + +#include "core/core_string_names.h" +#include "core/debugger/engine_debugger.h" +#include "core/object/class_db.h" +#include "core/templates/local_vector.h" +#include "core/variant/variant_internal.h" + +/**** NAMED SETTERS AND GETTERS ****/ + +#define SETGET_STRUCT(m_base_type, m_member_type, m_member) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + VariantTypeAdjust<m_member_type>::adjust(member); \ + *VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member; \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_member, member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg<m_base_type>::convert(base); \ + b.m_member = PtrToArg<m_member_type>::convert(member); \ + PtrToArg<m_base_type>::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \ + }; + +#define SETGET_NUMBER_STRUCT(m_base_type, m_member_type, m_member) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + VariantTypeAdjust<m_member_type>::adjust(member); \ + *VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member; \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_member, member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == Variant::FLOAT) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<double>::get_ptr(value); \ + valid = true; \ + } else if (value->get_type() == Variant::INT) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<int64_t>::get_ptr(value); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_member = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg<m_base_type>::convert(base); \ + b.m_member = PtrToArg<m_member_type>::convert(member); \ + PtrToArg<m_base_type>::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \ + }; + +#define SETGET_STRUCT_CUSTOM(m_base_type, m_member_type, m_member, m_custom) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + VariantTypeAdjust<m_member_type>::adjust(member); \ + *VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom; \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_custom, member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg<m_base_type>::convert(base); \ + b.m_custom = PtrToArg<m_member_type>::convert(member); \ + PtrToArg<m_base_type>::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \ + }; + +#define SETGET_NUMBER_STRUCT_CUSTOM(m_base_type, m_member_type, m_member, m_custom) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + VariantTypeAdjust<m_member_type>::adjust(member); \ + *VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom; \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_custom, member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == Variant::FLOAT) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<double>::get_ptr(value); \ + valid = true; \ + } else if (value->get_type() == Variant::INT) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<int64_t>::get_ptr(value); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_custom = *VariantGetInternalPtr<m_member_type>::get_ptr(value); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg<m_base_type>::convert(base); \ + b.m_custom = PtrToArg<m_member_type>::convert(member); \ + PtrToArg<m_base_type>::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \ + }; + +#define SETGET_STRUCT_FUNC(m_base_type, m_member_type, m_member, m_setter, m_getter) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + VariantTypeAdjust<m_member_type>::adjust(member); \ + *VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(); \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_getter(), member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<m_member_type>::get_ptr(value)); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<m_member_type>::get_ptr(value)); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg<m_base_type>::convert(base); \ + b.m_setter(PtrToArg<m_member_type>::convert(member)); \ + PtrToArg<m_base_type>::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \ + }; + +#define SETGET_NUMBER_STRUCT_FUNC(m_base_type, m_member_type, m_member, m_setter, m_getter) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + VariantTypeAdjust<m_member_type>::adjust(member); \ + *VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(); \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_getter(), member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == Variant::FLOAT) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<double>::get_ptr(value)); \ + valid = true; \ + } else if (value->get_type() == Variant::INT) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<int64_t>::get_ptr(value)); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(*VariantGetInternalPtr<m_member_type>::get_ptr(value)); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg<m_base_type>::convert(base); \ + b.m_setter(PtrToArg<m_member_type>::convert(member)); \ + PtrToArg<m_base_type>::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \ + }; + +#define SETGET_STRUCT_FUNC_INDEX(m_base_type, m_member_type, m_member, m_setter, m_getter, m_index) \ + struct VariantSetGet_##m_base_type##_##m_member { \ + static void get(const Variant *base, Variant *member) { \ + VariantTypeAdjust<m_member_type>::adjust(member); \ + *VariantGetInternalPtr<m_member_type>::get_ptr(member) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_getter(m_index); \ + } \ + static void ptr_get(const void *base, void *member) { \ + PtrToArg<m_member_type>::encode(PtrToArg<m_base_type>::convert(base).m_getter(m_index), member); \ + } \ + static void set(Variant *base, const Variant *value, bool &valid) { \ + if (value->get_type() == GetTypeInfo<m_member_type>::VARIANT_TYPE) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(m_index, *VariantGetInternalPtr<m_member_type>::get_ptr(value)); \ + valid = true; \ + } else { \ + valid = false; \ + } \ + } \ + static void validated_set(Variant *base, const Variant *value) { \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_setter(m_index, *VariantGetInternalPtr<m_member_type>::get_ptr(value)); \ + } \ + static void ptr_set(void *base, const void *member) { \ + m_base_type b = PtrToArg<m_base_type>::convert(base); \ + b.m_setter(m_index, PtrToArg<m_member_type>::convert(member)); \ + PtrToArg<m_base_type>::encode(b, base); \ + } \ + static Variant::Type get_type() { return GetTypeInfo<m_member_type>::VARIANT_TYPE; } \ + }; + +SETGET_NUMBER_STRUCT(Vector2, double, x) +SETGET_NUMBER_STRUCT(Vector2, double, y) + +SETGET_NUMBER_STRUCT(Vector2i, int64_t, x) +SETGET_NUMBER_STRUCT(Vector2i, int64_t, y) + +SETGET_NUMBER_STRUCT(Vector3, double, x) +SETGET_NUMBER_STRUCT(Vector3, double, y) +SETGET_NUMBER_STRUCT(Vector3, double, z) + +SETGET_NUMBER_STRUCT(Vector3i, int64_t, x) +SETGET_NUMBER_STRUCT(Vector3i, int64_t, y) +SETGET_NUMBER_STRUCT(Vector3i, int64_t, z) + +SETGET_STRUCT(Rect2, Vector2, position) +SETGET_STRUCT(Rect2, Vector2, size) +SETGET_STRUCT_FUNC(Rect2, Vector2, end, set_end, get_end) + +SETGET_STRUCT(Rect2i, Vector2i, position) +SETGET_STRUCT(Rect2i, Vector2i, size) +SETGET_STRUCT_FUNC(Rect2i, Vector2i, end, set_end, get_end) + +SETGET_STRUCT(AABB, Vector3, position) +SETGET_STRUCT(AABB, Vector3, size) +SETGET_STRUCT_FUNC(AABB, Vector3, end, set_end, get_end) + +SETGET_STRUCT_CUSTOM(Transform2D, Vector2, x, elements[0]) +SETGET_STRUCT_CUSTOM(Transform2D, Vector2, y, elements[1]) +SETGET_STRUCT_CUSTOM(Transform2D, Vector2, origin, elements[2]) + +SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, x, normal.x) +SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, y, normal.y) +SETGET_NUMBER_STRUCT_CUSTOM(Plane, double, z, normal.z) +SETGET_STRUCT(Plane, Vector3, normal) +SETGET_NUMBER_STRUCT(Plane, double, d) + +SETGET_NUMBER_STRUCT(Quat, double, x) +SETGET_NUMBER_STRUCT(Quat, double, y) +SETGET_NUMBER_STRUCT(Quat, double, z) +SETGET_NUMBER_STRUCT(Quat, double, w) + +SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, x, set_axis, get_axis, 0) +SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, y, set_axis, get_axis, 1) +SETGET_STRUCT_FUNC_INDEX(Basis, Vector3, z, set_axis, get_axis, 2) + +SETGET_STRUCT(Transform, Basis, basis) +SETGET_STRUCT(Transform, Vector3, origin) + +SETGET_NUMBER_STRUCT(Color, double, r) +SETGET_NUMBER_STRUCT(Color, double, g) +SETGET_NUMBER_STRUCT(Color, double, b) +SETGET_NUMBER_STRUCT(Color, double, a) + +SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, r8, set_r8, get_r8) +SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, g8, set_g8, get_g8) +SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, b8, set_b8, get_b8) +SETGET_NUMBER_STRUCT_FUNC(Color, int64_t, a8, set_a8, get_a8) + +SETGET_NUMBER_STRUCT_FUNC(Color, double, h, set_h, get_h) +SETGET_NUMBER_STRUCT_FUNC(Color, double, s, set_s, get_s) +SETGET_NUMBER_STRUCT_FUNC(Color, double, v, set_v, get_v) + +struct VariantSetterGetterInfo { + void (*setter)(Variant *base, const Variant *value, bool &valid); + void (*getter)(const Variant *base, Variant *value); + Variant::ValidatedSetter validated_setter; + Variant::ValidatedGetter validated_getter; + Variant::PTRSetter ptr_setter; + Variant::PTRGetter ptr_getter; + Variant::Type member_type; +}; + +static LocalVector<VariantSetterGetterInfo> variant_setters_getters[Variant::VARIANT_MAX]; +static LocalVector<StringName> variant_setters_getters_names[Variant::VARIANT_MAX]; //one next to another to make it cache friendly + +template <class T> +static void register_member(Variant::Type p_type, const StringName &p_member) { + VariantSetterGetterInfo sgi; + sgi.setter = T::set; + sgi.validated_setter = T::validated_set; + sgi.ptr_setter = T::ptr_set; + + sgi.getter = T::get; + sgi.validated_getter = T::get; + sgi.ptr_getter = T::ptr_get; + + sgi.member_type = T::get_type(); + + variant_setters_getters[p_type].push_back(sgi); + variant_setters_getters_names[p_type].push_back(p_member); +} + +void register_named_setters_getters() { +#define REGISTER_MEMBER(m_base_type, m_member) register_member<VariantSetGet_##m_base_type##_##m_member>(GetTypeInfo<m_base_type>::VARIANT_TYPE, #m_member) + + REGISTER_MEMBER(Vector2, x); + REGISTER_MEMBER(Vector2, y); + + REGISTER_MEMBER(Vector2i, x); + REGISTER_MEMBER(Vector2i, y); + + REGISTER_MEMBER(Vector3, x); + REGISTER_MEMBER(Vector3, y); + REGISTER_MEMBER(Vector3, z); + + REGISTER_MEMBER(Vector3i, x); + REGISTER_MEMBER(Vector3i, y); + REGISTER_MEMBER(Vector3i, z); + + REGISTER_MEMBER(Rect2, position); + REGISTER_MEMBER(Rect2, size); + REGISTER_MEMBER(Rect2, end); + + REGISTER_MEMBER(Rect2i, position); + REGISTER_MEMBER(Rect2i, size); + REGISTER_MEMBER(Rect2i, end); + + REGISTER_MEMBER(AABB, position); + REGISTER_MEMBER(AABB, size); + REGISTER_MEMBER(AABB, end); + + REGISTER_MEMBER(Transform2D, x); + REGISTER_MEMBER(Transform2D, y); + REGISTER_MEMBER(Transform2D, origin); + + REGISTER_MEMBER(Plane, x); + REGISTER_MEMBER(Plane, y); + REGISTER_MEMBER(Plane, z); + REGISTER_MEMBER(Plane, d); + REGISTER_MEMBER(Plane, normal); + + REGISTER_MEMBER(Quat, x); + REGISTER_MEMBER(Quat, y); + REGISTER_MEMBER(Quat, z); + REGISTER_MEMBER(Quat, w); + + REGISTER_MEMBER(Basis, x); + REGISTER_MEMBER(Basis, y); + REGISTER_MEMBER(Basis, z); + + REGISTER_MEMBER(Transform, basis); + REGISTER_MEMBER(Transform, origin); + + REGISTER_MEMBER(Color, r); + REGISTER_MEMBER(Color, g); + REGISTER_MEMBER(Color, b); + REGISTER_MEMBER(Color, a); + + REGISTER_MEMBER(Color, r8); + REGISTER_MEMBER(Color, g8); + REGISTER_MEMBER(Color, b8); + REGISTER_MEMBER(Color, a8); + + REGISTER_MEMBER(Color, h); + REGISTER_MEMBER(Color, s); + REGISTER_MEMBER(Color, v); +} + +void unregister_named_setters_getters() { + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + variant_setters_getters[i].clear(); + variant_setters_getters_names[i].clear(); + } +} + +bool Variant::has_member(Variant::Type p_type, const StringName &p_member) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); + + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + if (variant_setters_getters_names[p_type][i] == p_member) { + return true; + } + } + return false; +} + +Variant::Type Variant::get_member_type(Variant::Type p_type, const StringName &p_member) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::VARIANT_MAX); + + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + if (variant_setters_getters_names[p_type][i] == p_member) { + return variant_setters_getters[p_type][i].member_type; + } + } + + return Variant::NIL; +} + +void Variant::get_member_list(Variant::Type p_type, List<StringName> *r_members) { + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + r_members->push_back(variant_setters_getters_names[p_type][i]); + } +} + +int Variant::get_member_count(Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, -1); + return variant_setters_getters_names[p_type].size(); +} + +Variant::ValidatedSetter Variant::get_member_validated_setter(Variant::Type p_type, const StringName &p_member) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + if (variant_setters_getters_names[p_type][i] == p_member) { + return variant_setters_getters[p_type][i].validated_setter; + } + } + + return nullptr; +} +Variant::ValidatedGetter Variant::get_member_validated_getter(Variant::Type p_type, const StringName &p_member) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + if (variant_setters_getters_names[p_type][i] == p_member) { + return variant_setters_getters[p_type][i].validated_getter; + } + } + + return nullptr; +} + +Variant::PTRSetter Variant::get_member_ptr_setter(Variant::Type p_type, const StringName &p_member) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + if (variant_setters_getters_names[p_type][i] == p_member) { + return variant_setters_getters[p_type][i].ptr_setter; + } + } + + return nullptr; +} + +Variant::PTRGetter Variant::get_member_ptr_getter(Variant::Type p_type, const StringName &p_member) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + + for (uint32_t i = 0; i < variant_setters_getters_names[p_type].size(); i++) { + if (variant_setters_getters_names[p_type][i] == p_member) { + return variant_setters_getters[p_type][i].ptr_getter; + } + } + + return nullptr; +} + +void Variant::set_named(const StringName &p_member, const Variant &p_value, bool &r_valid) { + 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_setters_getters[type][i].setter(this, &p_value, r_valid); + return; + } + } + r_valid = false; + + } else if (type == Variant::OBJECT) { + Object *obj = get_validated_object(); + if (!obj) { + r_valid = false; + } else { + obj->set(p_member, p_value, &r_valid); + return; + } + } else if (type == Variant::DICTIONARY) { + Variant *v = VariantGetInternalPtr<Dictionary>::get_ptr(this)->getptr(p_member); + if (v) { + *v = p_value; + r_valid = true; + } else { + r_valid = false; + } + + } else { + r_valid = false; + } +} + +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_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; + } + + return ret; +} + +/**** INDEXED SETTERS AND GETTERS ****/ + +#ifdef DEBUG_ENABLED + +#define OOB_TEST(m_idx, m_v) \ + ERR_FAIL_INDEX(m_idx, m_v) + +#else + +#define OOB_TEST(m_idx, m_v) + +#endif + +#ifdef DEBUG_ENABLED + +#define NULL_TEST(m_key) \ + ERR_FAIL_COND(!m_key) + +#else + +#define NULL_TEST(m_key) + +#endif + +#define INDEXED_SETGET_STRUCT_TYPED(m_base_type, m_elem_type) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \ + int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + *oob = true; \ + return; \ + } \ + VariantTypeAdjust<m_elem_type>::adjust(value); \ + *VariantGetInternalPtr<m_elem_type>::get_ptr(value) = (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index]; \ + *oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \ + if (index < 0) \ + index += v.size(); \ + OOB_TEST(index, v.size()); \ + PtrToArg<m_elem_type>::encode(v[index], member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \ + if (value->get_type() != GetTypeInfo<m_elem_type>::VARIANT_TYPE) { \ + *oob = false; \ + *valid = false; \ + return; \ + } \ + int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + *oob = true; \ + *valid = false; \ + return; \ + } \ + (*VariantGetInternalPtr<m_base_type>::get_ptr(base)).write[index] = *VariantGetInternalPtr<m_elem_type>::get_ptr(value); \ + *oob = false; \ + *valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \ + int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + *oob = true; \ + return; \ + } \ + (*VariantGetInternalPtr<m_base_type>::get_ptr(base)).write[index] = *VariantGetInternalPtr<m_elem_type>::get_ptr(value); \ + *oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + /* avoid ptrconvert for performance*/ \ + m_base_type &v = *reinterpret_cast<m_base_type *>(base); \ + if (index < 0) \ + index += v.size(); \ + OOB_TEST(index, v.size()); \ + v.write[index] = PtrToArg<m_elem_type>::convert(member); \ + } \ + static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \ + static uint64_t get_indexed_size(const Variant *base) { return VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); } \ + }; + +#define INDEXED_SETGET_STRUCT_TYPED_NUMERIC(m_base_type, m_elem_type, m_assign_type) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \ + int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + *oob = true; \ + return; \ + } \ + VariantTypeAdjust<m_elem_type>::adjust(value); \ + *VariantGetInternalPtr<m_elem_type>::get_ptr(value) = (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index]; \ + *oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \ + if (index < 0) \ + index += v.size(); \ + OOB_TEST(index, v.size()); \ + PtrToArg<m_elem_type>::encode(v[index], member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \ + int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + *oob = true; \ + *valid = false; \ + return; \ + } \ + m_assign_type num; \ + if (value->get_type() == Variant::INT) { \ + num = (m_assign_type)*VariantGetInternalPtr<int64_t>::get_ptr(value); \ + } else if (value->get_type() == Variant::FLOAT) { \ + num = (m_assign_type)*VariantGetInternalPtr<double>::get_ptr(value); \ + } else { \ + *oob = false; \ + *valid = false; \ + return; \ + } \ + (*VariantGetInternalPtr<m_base_type>::get_ptr(base)).write[index] = num; \ + *oob = false; \ + *valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \ + int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + *oob = true; \ + return; \ + } \ + (*VariantGetInternalPtr<m_base_type>::get_ptr(base)).write[index] = *VariantGetInternalPtr<m_elem_type>::get_ptr(value); \ + *oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + /* avoid ptrconvert for performance*/ \ + m_base_type &v = *reinterpret_cast<m_base_type *>(base); \ + if (index < 0) \ + index += v.size(); \ + OOB_TEST(index, v.size()); \ + v.write[index] = PtrToArg<m_elem_type>::convert(member); \ + } \ + static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \ + static uint64_t get_indexed_size(const Variant *base) { return VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); } \ + }; + +#define INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(m_base_type, m_elem_type, m_assign_type, m_max) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \ + if (index < 0 || index >= m_max) { \ + *oob = true; \ + return; \ + } \ + VariantTypeAdjust<m_elem_type>::adjust(value); \ + *VariantGetInternalPtr<m_elem_type>::get_ptr(value) = (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index]; \ + *oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \ + OOB_TEST(index, m_max); \ + PtrToArg<m_elem_type>::encode(v[index], member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \ + if (index < 0 || index >= m_max) { \ + *oob = true; \ + *valid = false; \ + return; \ + } \ + m_assign_type num; \ + if (value->get_type() == Variant::INT) { \ + num = (m_assign_type)*VariantGetInternalPtr<int64_t>::get_ptr(value); \ + } else if (value->get_type() == Variant::FLOAT) { \ + num = (m_assign_type)*VariantGetInternalPtr<double>::get_ptr(value); \ + } else { \ + *oob = false; \ + *valid = false; \ + return; \ + } \ + (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = num; \ + *oob = false; \ + *valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \ + if (index < 0 || index >= m_max) { \ + *oob = true; \ + return; \ + } \ + (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *VariantGetInternalPtr<m_elem_type>::get_ptr(value); \ + *oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + /* avoid ptrconvert for performance*/ \ + m_base_type &v = *reinterpret_cast<m_base_type *>(base); \ + OOB_TEST(index, m_max); \ + v[index] = PtrToArg<m_elem_type>::convert(member); \ + } \ + static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \ + static uint64_t get_indexed_size(const Variant *base) { return m_max; } \ + }; + +#define INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(m_base_type, m_elem_type, m_accessor, m_max) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \ + if (index < 0 || index >= m_max) { \ + *oob = true; \ + return; \ + } \ + VariantTypeAdjust<m_elem_type>::adjust(value); \ + *VariantGetInternalPtr<m_elem_type>::get_ptr(value) = (*VariantGetInternalPtr<m_base_type>::get_ptr(base))m_accessor[index]; \ + *oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \ + OOB_TEST(index, m_max); \ + PtrToArg<m_elem_type>::encode(v m_accessor[index], member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \ + if (value->get_type() != GetTypeInfo<m_elem_type>::VARIANT_TYPE) { \ + *oob = false; \ + *valid = false; \ + } \ + if (index < 0 || index >= m_max) { \ + *oob = true; \ + *valid = false; \ + return; \ + } \ + (*VariantGetInternalPtr<m_base_type>::get_ptr(base)) m_accessor[index] = *VariantGetInternalPtr<m_elem_type>::get_ptr(value); \ + *oob = false; \ + *valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \ + if (index < 0 || index >= m_max) { \ + *oob = true; \ + return; \ + } \ + (*VariantGetInternalPtr<m_base_type>::get_ptr(base)) m_accessor[index] = *VariantGetInternalPtr<m_elem_type>::get_ptr(value); \ + *oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + /* avoid ptrconvert for performance*/ \ + m_base_type &v = *reinterpret_cast<m_base_type *>(base); \ + OOB_TEST(index, m_max); \ + v m_accessor[index] = PtrToArg<m_elem_type>::convert(member); \ + } \ + static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \ + static uint64_t get_indexed_size(const Variant *base) { return m_max; } \ + }; + +#define INDEXED_SETGET_STRUCT_BULTIN_FUNC(m_base_type, m_elem_type, m_set, m_get, m_max) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \ + if (index < 0 || index >= m_max) { \ + *oob = true; \ + return; \ + } \ + VariantTypeAdjust<m_elem_type>::adjust(value); \ + *VariantGetInternalPtr<m_elem_type>::get_ptr(value) = VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_get(index); \ + *oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \ + OOB_TEST(index, m_max); \ + PtrToArg<m_elem_type>::encode(v.m_get(index), member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \ + if (value->get_type() != GetTypeInfo<m_elem_type>::VARIANT_TYPE) { \ + *oob = false; \ + *valid = false; \ + } \ + if (index < 0 || index >= m_max) { \ + *oob = true; \ + *valid = false; \ + return; \ + } \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_set(index, *VariantGetInternalPtr<m_elem_type>::get_ptr(value)); \ + *oob = false; \ + *valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \ + if (index < 0 || index >= m_max) { \ + *oob = true; \ + return; \ + } \ + VariantGetInternalPtr<m_base_type>::get_ptr(base)->m_set(index, *VariantGetInternalPtr<m_elem_type>::get_ptr(value)); \ + *oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + /* avoid ptrconvert for performance*/ \ + m_base_type &v = *reinterpret_cast<m_base_type *>(base); \ + OOB_TEST(index, m_max); \ + v.m_set(index, PtrToArg<m_elem_type>::convert(member)); \ + } \ + static Variant::Type get_index_type() { return GetTypeInfo<m_elem_type>::VARIANT_TYPE; } \ + static uint64_t get_indexed_size(const Variant *base) { return m_max; } \ + }; + +#define INDEXED_SETGET_STRUCT_VARIANT(m_base_type) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \ + int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + *oob = true; \ + return; \ + } \ + *value = (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index]; \ + *oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \ + if (index < 0) \ + index += v.size(); \ + OOB_TEST(index, v.size()); \ + PtrToArg<Variant>::encode(v[index], member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \ + int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + *oob = true; \ + *valid = false; \ + return; \ + } \ + (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \ + *oob = false; \ + *valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \ + int64_t size = VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); \ + if (index < 0) { \ + index += size; \ + } \ + if (index < 0 || index >= size) { \ + *oob = true; \ + return; \ + } \ + (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \ + *oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + /* avoid ptrconvert for performance*/ \ + m_base_type &v = *reinterpret_cast<m_base_type *>(base); \ + if (index < 0) \ + index += v.size(); \ + OOB_TEST(index, v.size()); \ + v[index] = PtrToArg<Variant>::convert(member); \ + } \ + static Variant::Type get_index_type() { return Variant::NIL; } \ + static uint64_t get_indexed_size(const Variant *base) { return 0; } \ + }; + +#define INDEXED_SETGET_STRUCT_DICT(m_base_type) \ + struct VariantIndexedSetGet_##m_base_type { \ + static void get(const Variant *base, int64_t index, Variant *value, bool *oob) { \ + const Variant *ptr = VariantGetInternalPtr<m_base_type>::get_ptr(base)->getptr(index); \ + if (!ptr) { \ + *oob = true; \ + return; \ + } \ + *value = *ptr; \ + *oob = false; \ + } \ + static void ptr_get(const void *base, int64_t index, void *member) { \ + /* avoid ptrconvert for performance*/ \ + const m_base_type &v = *reinterpret_cast<const m_base_type *>(base); \ + const Variant *ptr = v.getptr(index); \ + NULL_TEST(ptr); \ + PtrToArg<Variant>::encode(*ptr, member); \ + } \ + static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) { \ + (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \ + *oob = false; \ + *valid = true; \ + } \ + static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) { \ + (*VariantGetInternalPtr<m_base_type>::get_ptr(base))[index] = *value; \ + *oob = false; \ + } \ + static void ptr_set(void *base, int64_t index, const void *member) { \ + m_base_type &v = *reinterpret_cast<m_base_type *>(base); \ + v[index] = PtrToArg<Variant>::convert(member); \ + } \ + static Variant::Type get_index_type() { return Variant::NIL; } \ + static uint64_t get_indexed_size(const Variant *base) { return VariantGetInternalPtr<m_base_type>::get_ptr(base)->size(); } \ + }; + +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector2, double, real_t, 2) +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector2i, int64_t, int32_t, 2) +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector3, double, real_t, 3) +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Vector3i, int64_t, int32_t, 3) +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Quat, double, real_t, 4) +INDEXED_SETGET_STRUCT_BULTIN_NUMERIC(Color, double, float, 4) + +INDEXED_SETGET_STRUCT_BULTIN_ACCESSOR(Transform2D, Vector2, .elements, 3) +INDEXED_SETGET_STRUCT_BULTIN_FUNC(Basis, Vector3, set_axis, get_axis, 3) + +INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedByteArray, int64_t, uint8_t) +INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedInt32Array, int64_t, int32_t) +INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedInt64Array, int64_t, int64_t) +INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedFloat32Array, double, float) +INDEXED_SETGET_STRUCT_TYPED_NUMERIC(PackedFloat64Array, double, double) +INDEXED_SETGET_STRUCT_TYPED(PackedVector2Array, Vector2) +INDEXED_SETGET_STRUCT_TYPED(PackedVector3Array, Vector3) +INDEXED_SETGET_STRUCT_TYPED(PackedStringArray, String) +INDEXED_SETGET_STRUCT_TYPED(PackedColorArray, Color) + +INDEXED_SETGET_STRUCT_VARIANT(Array) +INDEXED_SETGET_STRUCT_DICT(Dictionary) + +struct VariantIndexedSetterGetterInfo { + void (*setter)(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob); + void (*getter)(const Variant *base, int64_t index, Variant *value, bool *oob); + + Variant::ValidatedIndexedSetter validated_setter; + Variant::ValidatedIndexedGetter validated_getter; + + Variant::PTRIndexedSetter ptr_setter; + Variant::PTRIndexedGetter ptr_getter; + + uint64_t (*get_indexed_size)(const Variant *base); + + Variant::Type index_type; + + bool valid = false; +}; + +static VariantIndexedSetterGetterInfo variant_indexed_setters_getters[Variant::VARIANT_MAX]; + +template <class T> +static void register_indexed_member(Variant::Type p_type) { + VariantIndexedSetterGetterInfo &sgi = variant_indexed_setters_getters[p_type]; + + sgi.setter = T::set; + sgi.validated_setter = T::validated_set; + sgi.ptr_setter = T::ptr_set; + + sgi.getter = T::get; + sgi.validated_getter = T::get; + sgi.ptr_getter = T::ptr_get; + + sgi.index_type = T::get_index_type(); + sgi.get_indexed_size = T::get_indexed_size; + + sgi.valid = true; +} + +void register_indexed_setters_getters() { +#define REGISTER_INDEXED_MEMBER(m_base_type) register_indexed_member<VariantIndexedSetGet_##m_base_type>(GetTypeInfo<m_base_type>::VARIANT_TYPE) + + REGISTER_INDEXED_MEMBER(Vector2); + REGISTER_INDEXED_MEMBER(Vector2i); + REGISTER_INDEXED_MEMBER(Vector3); + REGISTER_INDEXED_MEMBER(Vector3i); + REGISTER_INDEXED_MEMBER(Quat); + REGISTER_INDEXED_MEMBER(Color); + REGISTER_INDEXED_MEMBER(Transform2D); + REGISTER_INDEXED_MEMBER(Basis); + + REGISTER_INDEXED_MEMBER(PackedByteArray); + REGISTER_INDEXED_MEMBER(PackedInt32Array); + REGISTER_INDEXED_MEMBER(PackedInt64Array); + REGISTER_INDEXED_MEMBER(PackedFloat64Array); + REGISTER_INDEXED_MEMBER(PackedVector2Array); + REGISTER_INDEXED_MEMBER(PackedVector3Array); + REGISTER_INDEXED_MEMBER(PackedStringArray); + REGISTER_INDEXED_MEMBER(PackedColorArray); + + REGISTER_INDEXED_MEMBER(Array); + REGISTER_INDEXED_MEMBER(Dictionary); +} + +static void unregister_indexed_setters_getters() { +} + +bool Variant::has_indexing(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); + return variant_indexed_setters_getters[p_type].valid; +} + +Variant::Type Variant::get_indexed_element_type(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, Variant::VARIANT_MAX); + return variant_indexed_setters_getters[p_type].index_type; +} + +Variant::ValidatedIndexedSetter Variant::get_member_validated_indexed_setter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + return variant_indexed_setters_getters[p_type].validated_setter; +} +Variant::ValidatedIndexedGetter Variant::get_member_validated_indexed_getter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + return variant_indexed_setters_getters[p_type].validated_getter; +} + +Variant::PTRIndexedSetter Variant::get_member_ptr_indexed_setter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + return variant_indexed_setters_getters[p_type].ptr_setter; +} +Variant::PTRIndexedGetter Variant::get_member_ptr_indexed_getter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, nullptr); + return variant_indexed_setters_getters[p_type].ptr_getter; +} + +void Variant::set_indexed(int64_t p_index, const Variant &p_value, bool &r_valid, bool &r_oob) { + if (likely(variant_indexed_setters_getters[type].valid)) { + variant_indexed_setters_getters[type].setter(this, p_index, &p_value, &r_valid, &r_oob); + } else { + r_valid = false; + r_oob = false; + } +} +Variant Variant::get_indexed(int64_t p_index, bool &r_valid, bool &r_oob) const { + if (likely(variant_indexed_setters_getters[type].valid)) { + Variant ret; + variant_indexed_setters_getters[type].getter(this, p_index, &ret, &r_oob); + r_valid = !r_oob; + return ret; + } else { + r_valid = false; + r_oob = false; + return Variant(); + } +} + +uint64_t Variant::get_indexed_size() const { + if (likely(variant_indexed_setters_getters[type].valid && variant_indexed_setters_getters[type].get_indexed_size)) { + return variant_indexed_setters_getters[type].get_indexed_size(this); + } else { + return 0; + } +} + +struct VariantKeyedSetGetDictionary { + static void get(const Variant *base, const Variant *key, Variant *value, bool *r_valid) { + const Variant *ptr = VariantGetInternalPtr<Dictionary>::get_ptr(base)->getptr(*key); + if (!ptr) { + *r_valid = false; + return; + } + *value = *ptr; + *r_valid = true; + } + static void ptr_get(const void *base, const void *key, void *value) { + /* avoid ptrconvert for performance*/ + const Dictionary &v = *reinterpret_cast<const Dictionary *>(base); + const Variant *ptr = v.getptr(PtrToArg<Variant>::convert(key)); + NULL_TEST(ptr); + PtrToArg<Variant>::encode(*ptr, value); + } + static void set(Variant *base, const Variant *key, const Variant *value, bool *r_valid) { + (*VariantGetInternalPtr<Dictionary>::get_ptr(base))[*key] = *value; + *r_valid = true; + } + static void ptr_set(void *base, const void *key, const void *value) { + Dictionary &v = *reinterpret_cast<Dictionary *>(base); + v[PtrToArg<Variant>::convert(key)] = PtrToArg<Variant>::convert(value); + } + + static bool has(const Variant *base, const Variant *key, bool *r_valid) { + *r_valid = true; + return VariantGetInternalPtr<Dictionary>::get_ptr(base)->has(*key); + } + static bool ptr_has(const void *base, const void *key) { + /* avoid ptrconvert for performance*/ + const Dictionary &v = *reinterpret_cast<const Dictionary *>(base); + return v.has(PtrToArg<Variant>::convert(key)); + } +}; + +struct VariantKeyedSetGetObject { + static void get(const Variant *base, const Variant *key, Variant *value, bool *r_valid) { + Object *obj = base->get_validated_object(); + + if (!obj) { + *r_valid = false; + *value = Variant(); + return; + } + *value = obj->getvar(*key, r_valid); + } + static void ptr_get(const void *base, const void *key, void *value) { + const Object *obj = PtrToArg<Object *>::convert(base); + NULL_TEST(obj); + Variant v = obj->getvar(PtrToArg<Variant>::convert(key)); + PtrToArg<Variant>::encode(v, value); + } + static void set(Variant *base, const Variant *key, const Variant *value, bool *r_valid) { + Object *obj = base->get_validated_object(); + + if (!obj) { + *r_valid = false; + return; + } + obj->setvar(*key, *value, r_valid); + } + static void ptr_set(void *base, const void *key, const void *value) { + Object *obj = PtrToArg<Object *>::convert(base); + NULL_TEST(obj); + obj->setvar(PtrToArg<Variant>::convert(key), PtrToArg<Variant>::convert(value)); + } + + static bool has(const Variant *base, const Variant *key, bool *r_valid) { + Object *obj = base->get_validated_object(); + if (!obj) { + *r_valid = false; + return false; + } + *r_valid = true; + bool exists; + obj->getvar(*key, &exists); + return exists; + } + static bool ptr_has(const void *base, const void *key) { + const Object *obj = PtrToArg<Object *>::convert(base); + ERR_FAIL_COND_V(!obj, false); + bool valid; + obj->getvar(PtrToArg<Variant>::convert(key), &valid); + return valid; + } +}; + +struct VariantKeyedSetterGetterInfo { + Variant::ValidatedKeyedSetter validated_setter; + Variant::ValidatedKeyedGetter validated_getter; + Variant::ValidatedKeyedChecker validated_checker; + + Variant::PTRKeyedSetter ptr_setter; + Variant::PTRKeyedGetter ptr_getter; + Variant::PTRKeyedChecker ptr_checker; + + bool valid = false; +}; + +static VariantKeyedSetterGetterInfo variant_keyed_setters_getters[Variant::VARIANT_MAX]; + +template <class T> +static void register_keyed_member(Variant::Type p_type) { + VariantKeyedSetterGetterInfo &sgi = variant_keyed_setters_getters[p_type]; + + sgi.validated_setter = T::set; + sgi.ptr_setter = T::ptr_set; + + sgi.validated_getter = T::get; + sgi.ptr_getter = T::ptr_get; + + sgi.validated_checker = T::has; + sgi.ptr_checker = T::ptr_has; + + sgi.valid = true; +} + +static void register_keyed_setters_getters() { + register_keyed_member<VariantKeyedSetGetDictionary>(Variant::DICTIONARY); + register_keyed_member<VariantKeyedSetGetObject>(Variant::OBJECT); +} +bool Variant::is_keyed(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, false); + return variant_keyed_setters_getters[p_type].valid; +} + +Variant::ValidatedKeyedSetter Variant::get_member_validated_keyed_setter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr); + return variant_keyed_setters_getters[p_type].validated_setter; +} +Variant::ValidatedKeyedGetter Variant::get_member_validated_keyed_getter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr); + return variant_keyed_setters_getters[p_type].validated_getter; +} +Variant::ValidatedKeyedChecker Variant::get_member_validated_keyed_checker(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr); + return variant_keyed_setters_getters[p_type].validated_checker; +} + +Variant::PTRKeyedSetter Variant::get_member_ptr_keyed_setter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr); + return variant_keyed_setters_getters[p_type].ptr_setter; +} +Variant::PTRKeyedGetter Variant::get_member_ptr_keyed_getter(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr); + return variant_keyed_setters_getters[p_type].ptr_getter; +} +Variant::PTRKeyedChecker Variant::get_member_ptr_keyed_checker(Variant::Type p_type) { + ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, nullptr); + return variant_keyed_setters_getters[p_type].ptr_checker; +} + +void Variant::set_keyed(const Variant &p_key, const Variant &p_value, bool &r_valid) { + if (likely(variant_keyed_setters_getters[type].valid)) { + variant_keyed_setters_getters[type].validated_setter(this, &p_key, &p_value, &r_valid); + } else { + r_valid = false; + } +} +Variant Variant::get_keyed(const Variant &p_key, bool &r_valid) const { + if (likely(variant_keyed_setters_getters[type].valid)) { + Variant ret; + variant_keyed_setters_getters[type].validated_getter(this, &p_key, &ret, &r_valid); + return ret; + } else { + r_valid = false; + return Variant(); + } +} +bool Variant::has_key(const Variant &p_key, bool &r_valid) const { + if (likely(variant_keyed_setters_getters[type].valid)) { + return variant_keyed_setters_getters[type].validated_checker(this, &p_key, &r_valid); + } else { + r_valid = false; + return false; + } +} + +void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) { + if (type == DICTIONARY || type == OBJECT) { + bool valid; + set_keyed(p_index, p_value, valid); + if (r_valid) { + *r_valid = valid; + } + } else { + bool valid = false; + if (p_index.get_type() == STRING_NAME) { + set_named(*VariantGetInternalPtr<StringName>::get_ptr(&p_index), p_value, valid); + } 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; + } + } else if (p_index.get_type() == STRING) { // less efficient version of named + set_named(*VariantGetInternalPtr<String>::get_ptr(&p_index), p_value, valid); + } 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 (r_valid) { + *r_valid = valid; + } + } +} + +Variant Variant::get(const Variant &p_index, bool *r_valid) const { + Variant ret; + if (type == DICTIONARY || type == OBJECT) { + bool valid; + ret = get_keyed(p_index, valid); + if (r_valid) { + *r_valid = valid; + } + } else { + bool valid = false; + if (p_index.get_type() == STRING_NAME) { + ret = get_named(*VariantGetInternalPtr<StringName>::get_ptr(&p_index), valid); + } 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; + } + } else if (p_index.get_type() == STRING) { // less efficient version of named + ret = get_named(*VariantGetInternalPtr<String>::get_ptr(&p_index), valid); + } 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 (r_valid) { + *r_valid = valid; + } + } + + return ret; +} + +void Variant::get_property_list(List<PropertyInfo> *p_list) const { + if (type == DICTIONARY) { + const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem); + List<Variant> keys; + dic->get_key_list(&keys); + for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { + if (E->get().get_type() == Variant::STRING) { + p_list->push_back(PropertyInfo(Variant::STRING, E->get())); + } + } + } else if (type == OBJECT) { + Object *obj = get_validated_object(); + ERR_FAIL_COND(!obj); + obj->get_property_list(p_list); + + } else { + List<StringName> members; + get_member_list(type, &members); + for (List<StringName>::Element *E = members.front(); E; E = E->next()) { + PropertyInfo pi; + pi.name = E->get(); + pi.type = get_member_type(type, E->get()); + p_list->push_back(pi); + } + } +} + +bool Variant::iter_init(Variant &r_iter, bool &valid) const { + valid = true; + switch (type) { + case INT: { + r_iter = 0; + return _data._int > 0; + } break; + case FLOAT: { + r_iter = 0; + return _data._float > 0.0; + } break; + case VECTOR2: { + double from = reinterpret_cast<const Vector2 *>(_data._mem)->x; + double to = reinterpret_cast<const Vector2 *>(_data._mem)->y; + + r_iter = from; + + return from < to; + } break; + case VECTOR2I: { + int64_t from = reinterpret_cast<const Vector2i *>(_data._mem)->x; + int64_t to = reinterpret_cast<const Vector2i *>(_data._mem)->y; + + r_iter = from; + + return from < to; + } break; + case VECTOR3: { + double from = reinterpret_cast<const Vector3 *>(_data._mem)->x; + double to = reinterpret_cast<const Vector3 *>(_data._mem)->y; + double step = reinterpret_cast<const Vector3 *>(_data._mem)->z; + + r_iter = from; + + if (from == to) { + return false; + } else if (from < to) { + return step > 0; + } + return step < 0; + } break; + case VECTOR3I: { + int64_t from = reinterpret_cast<const Vector3i *>(_data._mem)->x; + int64_t to = reinterpret_cast<const Vector3i *>(_data._mem)->y; + int64_t step = reinterpret_cast<const Vector3i *>(_data._mem)->z; + + r_iter = from; + + if (from == to) { + return false; + } else if (from < to) { + return step > 0; + } + return step < 0; + } break; + case OBJECT: { + if (!_get_obj().obj) { + valid = false; + return false; + } + +#ifdef DEBUG_ENABLED + + if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { + valid = false; + return false; + } + +#endif + Callable::CallError ce; + ce.error = Callable::CallError::CALL_OK; + Array ref; + ref.push_back(r_iter); + Variant vref = ref; + const Variant *refp[] = { &vref }; + Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_init, refp, 1, ce); + + if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) { + valid = false; + return false; + } + + r_iter = ref[0]; + return ret; + } break; + + case STRING: { + const String *str = reinterpret_cast<const String *>(_data._mem); + if (str->is_empty()) { + return false; + } + r_iter = 0; + return true; + } break; + case DICTIONARY: { + const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem); + if (dic->is_empty()) { + return false; + } + + const Variant *next = dic->next(nullptr); + r_iter = *next; + return true; + + } break; + case ARRAY: { + const Array *arr = reinterpret_cast<const Array *>(_data._mem); + if (arr->is_empty()) { + return false; + } + r_iter = 0; + return true; + } break; + case PACKED_BYTE_ARRAY: { + const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array); + if (arr->size() == 0) { + return false; + } + r_iter = 0; + return true; + + } break; + case PACKED_INT32_ARRAY: { + const Vector<int32_t> *arr = &PackedArrayRef<int32_t>::get_array(_data.packed_array); + if (arr->size() == 0) { + return false; + } + r_iter = 0; + return true; + + } break; + case PACKED_INT64_ARRAY: { + const Vector<int64_t> *arr = &PackedArrayRef<int64_t>::get_array(_data.packed_array); + if (arr->size() == 0) { + return false; + } + r_iter = 0; + return true; + + } break; + case PACKED_FLOAT32_ARRAY: { + const Vector<float> *arr = &PackedArrayRef<float>::get_array(_data.packed_array); + if (arr->size() == 0) { + return false; + } + r_iter = 0; + return true; + + } break; + case PACKED_FLOAT64_ARRAY: { + const Vector<double> *arr = &PackedArrayRef<double>::get_array(_data.packed_array); + if (arr->size() == 0) { + return false; + } + r_iter = 0; + return true; + + } break; + case PACKED_STRING_ARRAY: { + const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array); + if (arr->size() == 0) { + return false; + } + r_iter = 0; + return true; + } break; + case PACKED_VECTOR2_ARRAY: { + const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array); + if (arr->size() == 0) { + return false; + } + r_iter = 0; + return true; + } break; + case PACKED_VECTOR3_ARRAY: { + const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array); + if (arr->size() == 0) { + return false; + } + r_iter = 0; + return true; + } break; + case PACKED_COLOR_ARRAY: { + const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array); + if (arr->size() == 0) { + return false; + } + r_iter = 0; + return true; + + } break; + default: { + } + } + + valid = false; + return false; +} + +bool Variant::iter_next(Variant &r_iter, bool &valid) const { + valid = true; + switch (type) { + case INT: { + int64_t idx = r_iter; + idx++; + if (idx >= _data._int) { + return false; + } + r_iter = idx; + return true; + } break; + case FLOAT: { + int64_t idx = r_iter; + idx++; + if (idx >= _data._float) { + return false; + } + r_iter = idx; + return true; + } break; + case VECTOR2: { + double to = reinterpret_cast<const Vector2 *>(_data._mem)->y; + + double idx = r_iter; + idx++; + + if (idx >= to) { + return false; + } + + r_iter = idx; + return true; + } break; + case VECTOR2I: { + int64_t to = reinterpret_cast<const Vector2i *>(_data._mem)->y; + + int64_t idx = r_iter; + idx++; + + if (idx >= to) { + return false; + } + + r_iter = idx; + return true; + } break; + case VECTOR3: { + double to = reinterpret_cast<const Vector3 *>(_data._mem)->y; + double step = reinterpret_cast<const Vector3 *>(_data._mem)->z; + + double idx = r_iter; + idx += step; + + if (step < 0 && idx <= to) { + return false; + } + + if (step > 0 && idx >= to) { + return false; + } + + r_iter = idx; + return true; + } break; + case VECTOR3I: { + int64_t to = reinterpret_cast<const Vector3i *>(_data._mem)->y; + int64_t step = reinterpret_cast<const Vector3i *>(_data._mem)->z; + + int64_t idx = r_iter; + idx += step; + + if (step < 0 && idx <= to) { + return false; + } + + if (step > 0 && idx >= to) { + return false; + } + + r_iter = idx; + return true; + } break; + case OBJECT: { + if (!_get_obj().obj) { + valid = false; + return false; + } + +#ifdef DEBUG_ENABLED + + if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { + valid = false; + return false; + } + +#endif + Callable::CallError ce; + ce.error = Callable::CallError::CALL_OK; + Array ref; + ref.push_back(r_iter); + Variant vref = ref; + const Variant *refp[] = { &vref }; + Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_next, refp, 1, ce); + + if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) { + valid = false; + return false; + } + + r_iter = ref[0]; + + return ret; + } break; + + case STRING: { + const String *str = reinterpret_cast<const String *>(_data._mem); + int idx = r_iter; + idx++; + if (idx >= str->length()) { + return false; + } + r_iter = idx; + return true; + } break; + case DICTIONARY: { + const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem); + const Variant *next = dic->next(&r_iter); + if (!next) { + return false; + } + + r_iter = *next; + return true; + + } break; + case ARRAY: { + const Array *arr = reinterpret_cast<const Array *>(_data._mem); + int idx = r_iter; + idx++; + if (idx >= arr->size()) { + return false; + } + r_iter = idx; + return true; + } break; + case PACKED_BYTE_ARRAY: { + const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array); + int idx = r_iter; + idx++; + if (idx >= arr->size()) { + return false; + } + r_iter = idx; + return true; + + } break; + case PACKED_INT32_ARRAY: { + const Vector<int32_t> *arr = &PackedArrayRef<int32_t>::get_array(_data.packed_array); + int32_t idx = r_iter; + idx++; + if (idx >= arr->size()) { + return false; + } + r_iter = idx; + return true; + + } break; + case PACKED_INT64_ARRAY: { + const Vector<int64_t> *arr = &PackedArrayRef<int64_t>::get_array(_data.packed_array); + int64_t idx = r_iter; + idx++; + if (idx >= arr->size()) { + return false; + } + r_iter = idx; + return true; + + } break; + case PACKED_FLOAT32_ARRAY: { + const Vector<float> *arr = &PackedArrayRef<float>::get_array(_data.packed_array); + int idx = r_iter; + idx++; + if (idx >= arr->size()) { + return false; + } + r_iter = idx; + return true; + + } break; + case PACKED_FLOAT64_ARRAY: { + const Vector<double> *arr = &PackedArrayRef<double>::get_array(_data.packed_array); + int idx = r_iter; + idx++; + if (idx >= arr->size()) { + return false; + } + r_iter = idx; + return true; + + } break; + case PACKED_STRING_ARRAY: { + const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array); + int idx = r_iter; + idx++; + if (idx >= arr->size()) { + return false; + } + r_iter = idx; + return true; + } break; + case PACKED_VECTOR2_ARRAY: { + const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array); + int idx = r_iter; + idx++; + if (idx >= arr->size()) { + return false; + } + r_iter = idx; + return true; + } break; + case PACKED_VECTOR3_ARRAY: { + const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array); + int idx = r_iter; + idx++; + if (idx >= arr->size()) { + return false; + } + r_iter = idx; + return true; + } break; + case PACKED_COLOR_ARRAY: { + const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array); + int idx = r_iter; + idx++; + if (idx >= arr->size()) { + return false; + } + r_iter = idx; + return true; + } break; + default: { + } + } + + valid = false; + return false; +} + +Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { + r_valid = true; + switch (type) { + case INT: { + return r_iter; + } break; + case FLOAT: { + return r_iter; + } break; + case VECTOR2: { + return r_iter; + } break; + case VECTOR2I: { + return r_iter; + } break; + case VECTOR3: { + return r_iter; + } break; + case VECTOR3I: { + return r_iter; + } break; + case OBJECT: { + if (!_get_obj().obj) { + r_valid = false; + return Variant(); + } +#ifdef DEBUG_ENABLED + if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { + r_valid = false; + return Variant(); + } + +#endif + Callable::CallError ce; + ce.error = Callable::CallError::CALL_OK; + const Variant *refp[] = { &r_iter }; + Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_get, refp, 1, ce); + + if (ce.error != Callable::CallError::CALL_OK) { + r_valid = false; + return Variant(); + } + + //r_iter=ref[0]; + + return ret; + } break; + + case STRING: { + const String *str = reinterpret_cast<const String *>(_data._mem); + return str->substr(r_iter, 1); + } break; + case DICTIONARY: { + return r_iter; //iterator is the same as the key + + } break; + case ARRAY: { + const Array *arr = reinterpret_cast<const Array *>(_data._mem); + int idx = r_iter; +#ifdef DEBUG_ENABLED + if (idx < 0 || idx >= arr->size()) { + r_valid = false; + return Variant(); + } +#endif + return arr->get(idx); + } break; + case PACKED_BYTE_ARRAY: { + const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array); + int idx = r_iter; +#ifdef DEBUG_ENABLED + if (idx < 0 || idx >= arr->size()) { + r_valid = false; + return Variant(); + } +#endif + return arr->get(idx); + } break; + case PACKED_INT32_ARRAY: { + const Vector<int32_t> *arr = &PackedArrayRef<int32_t>::get_array(_data.packed_array); + int32_t idx = r_iter; +#ifdef DEBUG_ENABLED + if (idx < 0 || idx >= arr->size()) { + r_valid = false; + return Variant(); + } +#endif + return arr->get(idx); + } break; + case PACKED_INT64_ARRAY: { + const Vector<int64_t> *arr = &PackedArrayRef<int64_t>::get_array(_data.packed_array); + int64_t idx = r_iter; +#ifdef DEBUG_ENABLED + if (idx < 0 || idx >= arr->size()) { + r_valid = false; + return Variant(); + } +#endif + return arr->get(idx); + } break; + case PACKED_FLOAT32_ARRAY: { + const Vector<float> *arr = &PackedArrayRef<float>::get_array(_data.packed_array); + int idx = r_iter; +#ifdef DEBUG_ENABLED + if (idx < 0 || idx >= arr->size()) { + r_valid = false; + return Variant(); + } +#endif + return arr->get(idx); + } break; + case PACKED_FLOAT64_ARRAY: { + const Vector<double> *arr = &PackedArrayRef<double>::get_array(_data.packed_array); + int idx = r_iter; +#ifdef DEBUG_ENABLED + if (idx < 0 || idx >= arr->size()) { + r_valid = false; + return Variant(); + } +#endif + return arr->get(idx); + } break; + case PACKED_STRING_ARRAY: { + const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array); + int idx = r_iter; +#ifdef DEBUG_ENABLED + if (idx < 0 || idx >= arr->size()) { + r_valid = false; + return Variant(); + } +#endif + return arr->get(idx); + } break; + case PACKED_VECTOR2_ARRAY: { + const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array); + int idx = r_iter; +#ifdef DEBUG_ENABLED + if (idx < 0 || idx >= arr->size()) { + r_valid = false; + return Variant(); + } +#endif + return arr->get(idx); + } break; + case PACKED_VECTOR3_ARRAY: { + const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array); + int idx = r_iter; +#ifdef DEBUG_ENABLED + if (idx < 0 || idx >= arr->size()) { + r_valid = false; + return Variant(); + } +#endif + return arr->get(idx); + } break; + case PACKED_COLOR_ARRAY: { + const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array); + int idx = r_iter; +#ifdef DEBUG_ENABLED + if (idx < 0 || idx >= arr->size()) { + r_valid = false; + return Variant(); + } +#endif + return arr->get(idx); + } break; + default: { + } + } + + r_valid = false; + return Variant(); +} + +Variant Variant::duplicate(bool deep) const { + switch (type) { + case OBJECT: { + /* breaks stuff :( + if (deep && !_get_obj().ref.is_null()) { + Ref<Resource> resource = _get_obj().ref; + if (resource.is_valid()) { + return resource->duplicate(true); + } + } + */ + return *this; + } break; + case DICTIONARY: + return operator Dictionary().duplicate(deep); + case ARRAY: + return operator Array().duplicate(deep); + case PACKED_BYTE_ARRAY: + return operator Vector<uint8_t>().duplicate(); + case PACKED_INT32_ARRAY: + return operator Vector<int32_t>().duplicate(); + case PACKED_INT64_ARRAY: + return operator Vector<int64_t>().duplicate(); + case PACKED_FLOAT32_ARRAY: + return operator Vector<float>().duplicate(); + case PACKED_FLOAT64_ARRAY: + return operator Vector<double>().duplicate(); + case PACKED_STRING_ARRAY: + return operator Vector<String>().duplicate(); + case PACKED_VECTOR2_ARRAY: + return operator Vector<Vector2>().duplicate(); + case PACKED_VECTOR3_ARRAY: + return operator Vector<Vector3>().duplicate(); + case PACKED_COLOR_ARRAY: + return operator Vector<Color>().duplicate(); + default: + return *this; + } +} + +void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) { + if (a.type != b.type) { + if (a.is_num() && b.is_num()) { + real_t va = a; + real_t vb = b; + r_dst = va + vb * c; + } else { + r_dst = a; + } + return; + } + + switch (a.type) { + case NIL: { + r_dst = Variant(); + } + return; + case INT: { + int64_t va = a._data._int; + int64_t vb = b._data._int; + r_dst = int(va + vb * c + 0.5); + } + return; + case FLOAT: { + double ra = a._data._float; + double rb = b._data._float; + r_dst = ra + rb * c; + } + return; + case VECTOR2: { + r_dst = *reinterpret_cast<const Vector2 *>(a._data._mem) + *reinterpret_cast<const Vector2 *>(b._data._mem) * c; + } + return; + case VECTOR2I: { + int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x; + int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x; + int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y; + int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y; + r_dst = Vector2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5)); + } + return; + case RECT2: { + const Rect2 *ra = reinterpret_cast<const Rect2 *>(a._data._mem); + const Rect2 *rb = reinterpret_cast<const Rect2 *>(b._data._mem); + r_dst = Rect2(ra->position + rb->position * c, ra->size + rb->size * c); + } + return; + case RECT2I: { + const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem); + const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem); + + int32_t vax = ra->position.x; + int32_t vay = ra->position.y; + int32_t vbx = ra->size.x; + int32_t vby = ra->size.y; + int32_t vcx = rb->position.x; + int32_t vcy = rb->position.y; + int32_t vdx = rb->size.x; + int32_t vdy = rb->size.y; + + r_dst = Rect2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vcx + vdx * c + 0.5), int32_t(vcy + vdy * c + 0.5)); + } + return; + case VECTOR3: { + r_dst = *reinterpret_cast<const Vector3 *>(a._data._mem) + *reinterpret_cast<const Vector3 *>(b._data._mem) * c; + } + return; + case VECTOR3I: { + int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x; + int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x; + int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y; + int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y; + int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z; + int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z; + r_dst = Vector3i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vaz + vbz * c + 0.5)); + } + return; + case AABB: { + const ::AABB *ra = reinterpret_cast<const ::AABB *>(a._data._mem); + const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem); + r_dst = ::AABB(ra->position + rb->position * c, ra->size + rb->size * c); + } + return; + case QUAT: { + Quat empty_rot; + const Quat *qa = reinterpret_cast<const Quat *>(a._data._mem); + const Quat *qb = reinterpret_cast<const Quat *>(b._data._mem); + r_dst = *qa * empty_rot.slerp(*qb, c); + } + return; + case COLOR: { + const Color *ca = reinterpret_cast<const Color *>(a._data._mem); + const Color *cb = reinterpret_cast<const Color *>(b._data._mem); + float new_r = ca->r + cb->r * c; + float new_g = ca->g + cb->g * c; + float new_b = ca->b + cb->b * c; + float new_a = ca->a + cb->a * c; + new_r = new_r > 1.0 ? 1.0 : new_r; + new_g = new_g > 1.0 ? 1.0 : new_g; + new_b = new_b > 1.0 ? 1.0 : new_b; + new_a = new_a > 1.0 ? 1.0 : new_a; + r_dst = Color(new_r, new_g, new_b, new_a); + } + return; + default: { + r_dst = c < 0.5 ? a : b; + } + return; + } +} + +void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst) { + if (a.type != b.type) { + if (a.is_num() && b.is_num()) { + //not as efficient but.. + real_t va = a; + real_t vb = b; + r_dst = va + (vb - va) * c; + + } else { + r_dst = a; + } + return; + } + + switch (a.type) { + case NIL: { + r_dst = Variant(); + } + return; + case BOOL: { + r_dst = a; + } + return; + case INT: { + int64_t va = a._data._int; + int64_t vb = b._data._int; + r_dst = int(va + (vb - va) * c); + } + return; + case FLOAT: { + real_t va = a._data._float; + real_t vb = b._data._float; + r_dst = va + (vb - va) * c; + } + return; + case STRING: { + //this is pretty funny and bizarre, but artists like to use it for typewritter effects + String sa = *reinterpret_cast<const String *>(a._data._mem); + String sb = *reinterpret_cast<const String *>(b._data._mem); + String dst; + int sa_len = sa.length(); + int sb_len = sb.length(); + int csize = sa_len + (sb_len - sa_len) * c; + if (csize == 0) { + r_dst = ""; + return; + } + dst.resize(csize + 1); + dst[csize] = 0; + int split = csize / 2; + + for (int i = 0; i < csize; i++) { + char32_t chr = ' '; + + if (i < split) { + if (i < sa.length()) { + chr = sa[i]; + } else if (i < sb.length()) { + chr = sb[i]; + } + + } else { + if (i < sb.length()) { + chr = sb[i]; + } else if (i < sa.length()) { + chr = sa[i]; + } + } + + dst[i] = chr; + } + + r_dst = dst; + } + return; + case VECTOR2: { + r_dst = reinterpret_cast<const Vector2 *>(a._data._mem)->lerp(*reinterpret_cast<const Vector2 *>(b._data._mem), c); + } + return; + case VECTOR2I: { + int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x; + int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x; + int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y; + int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y; + r_dst = Vector2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5)); + } + return; + + case RECT2: { + r_dst = Rect2(reinterpret_cast<const Rect2 *>(a._data._mem)->position.lerp(reinterpret_cast<const Rect2 *>(b._data._mem)->position, c), reinterpret_cast<const Rect2 *>(a._data._mem)->size.lerp(reinterpret_cast<const Rect2 *>(b._data._mem)->size, c)); + } + return; + case RECT2I: { + const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem); + const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem); + + int32_t vax = ra->position.x; + int32_t vay = ra->position.y; + int32_t vbx = ra->size.x; + int32_t vby = ra->size.y; + int32_t vcx = rb->position.x; + int32_t vcy = rb->position.y; + int32_t vdx = rb->size.x; + int32_t vdy = rb->size.y; + + r_dst = Rect2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vcx + vdx * c + 0.5), int32_t(vcy + vdy * c + 0.5)); + } + return; + + case VECTOR3: { + r_dst = reinterpret_cast<const Vector3 *>(a._data._mem)->lerp(*reinterpret_cast<const Vector3 *>(b._data._mem), c); + } + return; + case VECTOR3I: { + int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x; + int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x; + int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y; + int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y; + int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z; + int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z; + r_dst = Vector3i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vaz + vbz * c + 0.5)); + } + return; + + case TRANSFORM2D: { + r_dst = a._data._transform2d->interpolate_with(*b._data._transform2d, c); + } + return; + case PLANE: { + r_dst = a; + } + return; + case QUAT: { + r_dst = reinterpret_cast<const Quat *>(a._data._mem)->slerp(*reinterpret_cast<const Quat *>(b._data._mem), c); + } + return; + case AABB: { + r_dst = ::AABB(a._data._aabb->position.lerp(b._data._aabb->position, c), a._data._aabb->size.lerp(b._data._aabb->size, c)); + } + return; + case BASIS: { + r_dst = Transform(*a._data._basis).interpolate_with(Transform(*b._data._basis), c).basis; + } + return; + case TRANSFORM: { + r_dst = a._data._transform->interpolate_with(*b._data._transform, c); + } + return; + case COLOR: { + r_dst = reinterpret_cast<const Color *>(a._data._mem)->lerp(*reinterpret_cast<const Color *>(b._data._mem), c); + } + return; + case STRING_NAME: { + r_dst = a; + } + return; + case NODE_PATH: { + r_dst = a; + } + return; + case RID: { + r_dst = a; + } + return; + case OBJECT: { + r_dst = a; + } + return; + case DICTIONARY: { + } + return; + case ARRAY: { + r_dst = a; + } + return; + case PACKED_BYTE_ARRAY: { + r_dst = a; + } + return; + case PACKED_INT32_ARRAY: { + const Vector<int32_t> *arr_a = &PackedArrayRef<int32_t>::get_array(a._data.packed_array); + const Vector<int32_t> *arr_b = &PackedArrayRef<int32_t>::get_array(b._data.packed_array); + int32_t sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + r_dst = a; + } else { + Vector<int32_t> v; + v.resize(sz); + { + int32_t *vw = v.ptrw(); + const int32_t *ar = arr_a->ptr(); + const int32_t *br = arr_b->ptr(); + + Variant va; + for (int32_t i = 0; i < sz; i++) { + Variant::interpolate(ar[i], br[i], c, va); + vw[i] = va; + } + } + r_dst = v; + } + } + return; + case PACKED_INT64_ARRAY: { + const Vector<int64_t> *arr_a = &PackedArrayRef<int64_t>::get_array(a._data.packed_array); + const Vector<int64_t> *arr_b = &PackedArrayRef<int64_t>::get_array(b._data.packed_array); + int64_t sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + r_dst = a; + } else { + Vector<int64_t> v; + v.resize(sz); + { + int64_t *vw = v.ptrw(); + const int64_t *ar = arr_a->ptr(); + const int64_t *br = arr_b->ptr(); + + Variant va; + for (int64_t i = 0; i < sz; i++) { + Variant::interpolate(ar[i], br[i], c, va); + vw[i] = va; + } + } + r_dst = v; + } + } + return; + case PACKED_FLOAT32_ARRAY: { + const Vector<float> *arr_a = &PackedArrayRef<float>::get_array(a._data.packed_array); + const Vector<float> *arr_b = &PackedArrayRef<float>::get_array(b._data.packed_array); + int sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + r_dst = a; + } else { + Vector<float> v; + v.resize(sz); + { + float *vw = v.ptrw(); + const float *ar = arr_a->ptr(); + const float *br = arr_b->ptr(); + + Variant va; + for (int i = 0; i < sz; i++) { + Variant::interpolate(ar[i], br[i], c, va); + vw[i] = va; + } + } + r_dst = v; + } + } + return; + case PACKED_FLOAT64_ARRAY: { + const Vector<double> *arr_a = &PackedArrayRef<double>::get_array(a._data.packed_array); + const Vector<double> *arr_b = &PackedArrayRef<double>::get_array(b._data.packed_array); + int sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + r_dst = a; + } else { + Vector<double> v; + v.resize(sz); + { + double *vw = v.ptrw(); + const double *ar = arr_a->ptr(); + const double *br = arr_b->ptr(); + + Variant va; + for (int i = 0; i < sz; i++) { + Variant::interpolate(ar[i], br[i], c, va); + vw[i] = va; + } + } + r_dst = v; + } + } + return; + case PACKED_STRING_ARRAY: { + r_dst = a; + } + return; + case PACKED_VECTOR2_ARRAY: { + const Vector<Vector2> *arr_a = &PackedArrayRef<Vector2>::get_array(a._data.packed_array); + const Vector<Vector2> *arr_b = &PackedArrayRef<Vector2>::get_array(b._data.packed_array); + int sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + r_dst = a; + } else { + Vector<Vector2> v; + v.resize(sz); + { + Vector2 *vw = v.ptrw(); + const Vector2 *ar = arr_a->ptr(); + const Vector2 *br = arr_b->ptr(); + + for (int i = 0; i < sz; i++) { + vw[i] = ar[i].lerp(br[i], c); + } + } + r_dst = v; + } + } + return; + case PACKED_VECTOR3_ARRAY: { + const Vector<Vector3> *arr_a = &PackedArrayRef<Vector3>::get_array(a._data.packed_array); + const Vector<Vector3> *arr_b = &PackedArrayRef<Vector3>::get_array(b._data.packed_array); + int sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + r_dst = a; + } else { + Vector<Vector3> v; + v.resize(sz); + { + Vector3 *vw = v.ptrw(); + const Vector3 *ar = arr_a->ptr(); + const Vector3 *br = arr_b->ptr(); + + for (int i = 0; i < sz; i++) { + vw[i] = ar[i].lerp(br[i], c); + } + } + r_dst = v; + } + } + return; + case PACKED_COLOR_ARRAY: { + const Vector<Color> *arr_a = &PackedArrayRef<Color>::get_array(a._data.packed_array); + const Vector<Color> *arr_b = &PackedArrayRef<Color>::get_array(b._data.packed_array); + int sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + r_dst = a; + } else { + Vector<Color> v; + v.resize(sz); + { + Color *vw = v.ptrw(); + const Color *ar = arr_a->ptr(); + const Color *br = arr_b->ptr(); + + for (int i = 0; i < sz; i++) { + vw[i] = ar[i].lerp(br[i], c); + } + } + r_dst = v; + } + } + return; + default: { + r_dst = a; + } + } +} + +void Variant::_register_variant_setters_getters() { + register_named_setters_getters(); + register_indexed_setters_getters(); + register_keyed_setters_getters(); +} +void Variant::_unregister_variant_setters_getters() { + unregister_named_setters_getters(); + unregister_indexed_setters_getters(); +} diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp new file mode 100644 index 0000000000..caa0bfdbb1 --- /dev/null +++ b/core/variant/variant_utility.cpp @@ -0,0 +1,1385 @@ +/*************************************************************************/ +/* variant_utility.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "variant.h" + +#include "core/core_string_names.h" +#include "core/io/marshalls.h" +#include "core/object/reference.h" +#include "core/os/os.h" +#include "core/templates/oa_hash_map.h" +#include "core/variant/binder_common.h" +#include "core/variant/variant_parser.h" + +struct VariantUtilityFunctions { + // Math + + static inline double sin(double arg) { + return Math::sin(arg); + } + + static inline double cos(double arg) { + return Math::cos(arg); + } + + static inline double tan(double arg) { + return Math::tan(arg); + } + + static inline double sinh(double arg) { + return Math::sinh(arg); + } + + static inline double cosh(double arg) { + return Math::cosh(arg); + } + + static inline double tanh(double arg) { + return Math::tanh(arg); + } + + static inline double asin(double arg) { + return Math::asin(arg); + } + + static inline double acos(double arg) { + return Math::acos(arg); + } + + static inline double atan(double arg) { + return Math::atan(arg); + } + + static inline double atan2(double y, double x) { + return Math::atan2(y, x); + } + + static inline double sqrt(double x) { + return Math::sqrt(x); + } + + static inline double fmod(double b, double r) { + return Math::fmod(b, r); + } + + static inline double fposmod(double b, double r) { + return Math::fposmod(b, r); + } + + static inline double floor(double x) { + return Math::floor(x); + } + + static inline double ceil(double x) { + return Math::ceil(x); + } + + static inline double round(double x) { + return Math::round(x); + } + + static inline Variant abs(const Variant &x, Callable::CallError &r_error) { + r_error.error = Callable::CallError::CALL_OK; + switch (x.get_type()) { + case Variant::INT: { + return ABS(VariantInternalAccessor<int64_t>::get(&x)); + } break; + case Variant::FLOAT: { + return Math::absd(VariantInternalAccessor<double>::get(&x)); + } break; + case Variant::VECTOR2: { + return VariantInternalAccessor<Vector2>::get(&x).abs(); + } break; + case Variant::VECTOR2I: { + return VariantInternalAccessor<Vector2i>::get(&x).abs(); + } break; + case Variant::VECTOR3: { + return VariantInternalAccessor<Vector3>::get(&x).abs(); + } break; + case Variant::VECTOR3I: { + return VariantInternalAccessor<Vector3i>::get(&x).abs(); + } break; + default: { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); + } + } + } + + static inline double absf(double x) { + return Math::absd(x); + } + + static inline int64_t absi(int64_t x) { + return ABS(x); + } + + static inline Variant sign(const Variant &x, Callable::CallError &r_error) { + r_error.error = Callable::CallError::CALL_OK; + switch (x.get_type()) { + case Variant::INT: { + return SGN(VariantInternalAccessor<int64_t>::get(&x)); + } break; + case Variant::FLOAT: { + return SGN(VariantInternalAccessor<double>::get(&x)); + } break; + case Variant::VECTOR2: { + return VariantInternalAccessor<Vector2>::get(&x).sign(); + } break; + case Variant::VECTOR2I: { + return VariantInternalAccessor<Vector2i>::get(&x).sign(); + } break; + case Variant::VECTOR3: { + return VariantInternalAccessor<Vector3>::get(&x).sign(); + } break; + case Variant::VECTOR3I: { + return VariantInternalAccessor<Vector3i>::get(&x).sign(); + } break; + default: { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + return Variant(); + } + } + } + + static inline double signf(double x) { + return SGN(x); + } + + static inline int64_t signi(int64_t x) { + return SGN(x); + } + + static inline double pow(double x, double y) { + return Math::pow(x, y); + } + + static inline double log(double x) { + return Math::log(x); + } + + static inline double exp(double x) { + return Math::exp(x); + } + + static inline bool is_nan(double x) { + return Math::is_nan(x); + } + + static inline bool is_inf(double x) { + return Math::is_inf(x); + } + + static inline bool is_equal_approx(double x, double y) { + return Math::is_equal_approx(x, y); + } + + static inline bool is_zero_approx(double x) { + return Math::is_zero_approx(x); + } + + static inline double ease(float x, float curve) { + return Math::ease(x, curve); + } + + static inline int step_decimals(float step) { + return Math::step_decimals(step); + } + + static inline int range_step_decimals(float step) { + return Math::range_step_decimals(step); + } + + static inline double snapped(double value, double step) { + return Math::snapped(value, step); + } + + static inline double lerp(double from, double to, double weight) { + return Math::lerp(from, to, weight); + } + + static inline double lerp_angle(double from, double to, double weight) { + return Math::lerp_angle(from, to, weight); + } + + static inline double inverse_lerp(double from, double to, double weight) { + return Math::inverse_lerp(from, to, weight); + } + + static inline double range_lerp(double value, double istart, double istop, double ostart, double ostop) { + return Math::range_lerp(value, istart, istop, ostart, ostop); + } + + static inline double smoothstep(double from, double to, double val) { + return Math::smoothstep(from, to, val); + } + + static inline double move_toward(double from, double to, double delta) { + return Math::move_toward(from, to, delta); + } + + static inline double dectime(double value, double amount, double step) { + return Math::dectime(value, amount, step); + } + + static inline double deg2rad(double angle_deg) { + return Math::deg2rad(angle_deg); + } + + static inline double rad2deg(double angle_rad) { + return Math::rad2deg(angle_rad); + } + + static inline double linear2db(double linear) { + return Math::linear2db(linear); + } + + static inline double db2linear(double db) { + return Math::db2linear(db); + } + + static inline Vector2 polar2cartesian(double r, double th) { + return Vector2(r * Math::cos(th), r * Math::sin(th)); + } + + static inline Vector2 cartesian2polar(double x, double y) { + return Vector2(Math::sqrt(x * x + y * y), Math::atan2(y, x)); + } + + static inline int64_t wrapi(int64_t value, int64_t min, int64_t max) { + return Math::wrapi(value, min, max); + } + + static inline double wrapf(double value, double min, double max) { + return Math::wrapf(value, min, max); + } + + static inline Variant max(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + if (p_argcount < 2) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.expected = 2; + return Variant(); + } + Variant base = *p_args[0]; + Variant ret; + for (int i = 1; i < p_argcount; i++) { + bool valid; + Variant::evaluate(Variant::OP_GREATER, base, *p_args[i], ret, valid); + if (!valid) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.expected = base.get_type(); + r_error.argument = i; + return Variant(); + } + if (ret.booleanize()) { + base = *p_args[i]; + } + } + r_error.error = Callable::CallError::CALL_OK; + return base; + } + + static inline double maxf(double x, double y) { + return MAX(x, y); + } + + static inline int64_t maxi(int64_t x, int64_t y) { + return MAX(x, y); + } + + static inline Variant min(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + if (p_argcount < 2) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.expected = 2; + return Variant(); + } + Variant base = *p_args[0]; + Variant ret; + for (int i = 1; i < p_argcount; i++) { + bool valid; + Variant::evaluate(Variant::OP_LESS, base, *p_args[i], ret, valid); + if (!valid) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.expected = base.get_type(); + r_error.argument = i; + return Variant(); + } + if (ret.booleanize()) { + base = *p_args[i]; + } + } + r_error.error = Callable::CallError::CALL_OK; + return base; + } + + static inline double minf(double x, double y) { + return MIN(x, y); + } + + static inline int64_t mini(int64_t x, int64_t y) { + return MIN(x, y); + } + + static inline Variant clamp(const Variant &x, const Variant &min, const Variant &max, Callable::CallError &r_error) { + Variant value = x; + + Variant ret; + + bool valid; + Variant::evaluate(Variant::OP_LESS, value, min, ret, valid); + if (!valid) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.expected = value.get_type(); + r_error.argument = 1; + return Variant(); + } + if (ret.booleanize()) { + value = min; + } + Variant::evaluate(Variant::OP_GREATER, value, max, ret, valid); + if (!valid) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.expected = value.get_type(); + r_error.argument = 2; + return Variant(); + } + if (ret.booleanize()) { + value = max; + } + + r_error.error = Callable::CallError::CALL_OK; + + return value; + } + + static inline double clampf(double x, double min, double max) { + return CLAMP(x, min, max); + } + + static inline int64_t clampi(int64_t x, int64_t min, int64_t max) { + return CLAMP(x, min, max); + } + + static inline int64_t nearest_po2(int64_t x) { + return nearest_power_of_2_templated(uint64_t(x)); + } + + // Random + + static inline void randomize() { + Math::randomize(); + } + + static inline int64_t randi() { + return Math::rand(); + } + + static inline double randf() { + return Math::randf(); + } + + static inline int64_t randi_range(int64_t from, int64_t to) { + return Math::random((int32_t)from, (int32_t)to); + } + + static inline double randf_range(double from, double to) { + return Math::random(from, to); + } + + static inline void seed(int64_t s) { + return Math::seed(s); + } + + static inline PackedInt64Array rand_from_seed(int64_t seed) { + uint64_t s = seed; + PackedInt64Array arr; + arr.resize(2); + arr.write[0] = Math::rand_from_seed(&s); + arr.write[1] = s; + return arr; + } + + // Utility + + static inline Variant weakref(const Variant &obj, Callable::CallError &r_error) { + if (obj.get_type() == Variant::OBJECT) { + r_error.error = Callable::CallError::CALL_OK; + if (obj.is_ref()) { + Ref<WeakRef> wref = memnew(WeakRef); + REF r = obj; + if (r.is_valid()) { + wref->set_ref(r); + } + return wref; + } else { + Ref<WeakRef> wref = memnew(WeakRef); + Object *o = obj.get_validated_object(); + if (o) { + wref->set_obj(o); + } + return wref; + } + } else if (obj.get_type() == Variant::NIL) { + r_error.error = Callable::CallError::CALL_OK; + Ref<WeakRef> wref = memnew(WeakRef); + return wref; + } else { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; + r_error.argument = 0; + r_error.expected = Variant::OBJECT; + return Variant(); + } + } + + static inline int64_t _typeof(const Variant &obj) { + return obj.get_type(); + } + + static inline String str(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + if (p_arg_count < 1) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 1; + return String(); + } + String str; + for (int i = 0; i < p_arg_count; i++) { + String os = p_args[i]->operator String(); + + if (i == 0) { + str = os; + } else { + str += os; + } + } + + r_error.error = Callable::CallError::CALL_OK; + + return str; + } + + static inline void print(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + if (p_arg_count < 1) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 1; + } + String str; + for (int i = 0; i < p_arg_count; i++) { + String os = p_args[i]->operator String(); + + if (i == 0) { + str = os; + } else { + str += os; + } + } + + print_line(str); + r_error.error = Callable::CallError::CALL_OK; + } + + static inline void printerr(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + if (p_arg_count < 1) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 1; + } + String str; + for (int i = 0; i < p_arg_count; i++) { + String os = p_args[i]->operator String(); + + if (i == 0) { + str = os; + } else { + str += os; + } + } + + print_error(str); + r_error.error = Callable::CallError::CALL_OK; + } + + static inline void printt(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + if (p_arg_count < 1) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 1; + } + String str; + for (int i = 0; i < p_arg_count; i++) { + if (i) { + str += "\t"; + } + str += p_args[i]->operator String(); + } + + print_line(str); + r_error.error = Callable::CallError::CALL_OK; + } + + static inline void prints(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + if (p_arg_count < 1) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 1; + } + String str; + for (int i = 0; i < p_arg_count; i++) { + if (i) { + str += " "; + } + str += p_args[i]->operator String(); + } + + print_line(str); + r_error.error = Callable::CallError::CALL_OK; + } + + static inline void printraw(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + if (p_arg_count < 1) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 1; + } + String str; + for (int i = 0; i < p_arg_count; i++) { + String os = p_args[i]->operator String(); + + if (i == 0) { + str = os; + } else { + str += os; + } + } + + OS::get_singleton()->print("%s", str.utf8().get_data()); + r_error.error = Callable::CallError::CALL_OK; + } + + static inline void push_error(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + if (p_arg_count < 1) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 1; + } + String str; + for (int i = 0; i < p_arg_count; i++) { + String os = p_args[i]->operator String(); + + if (i == 0) { + str = os; + } else { + str += os; + } + } + + ERR_PRINT(str); + r_error.error = Callable::CallError::CALL_OK; + } + + static inline void push_warning(const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + if (p_arg_count < 1) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 1; + } + String str; + for (int i = 0; i < p_arg_count; i++) { + String os = p_args[i]->operator String(); + + if (i == 0) { + str = os; + } else { + str += os; + } + } + + WARN_PRINT(str); + r_error.error = Callable::CallError::CALL_OK; + } + + static inline String var2str(const Variant &p_var) { + String vars; + VariantWriter::write_to_string(p_var, vars); + return vars; + } + + static inline Variant str2var(const String &p_var) { + VariantParser::StreamString ss; + ss.s = p_var; + + String errs; + int line; + Variant ret; + (void)VariantParser::parse(&ss, ret, errs, line); + + return ret; + } + + static inline PackedByteArray var2bytes(const Variant &p_var) { + int len; + Error err = encode_variant(p_var, nullptr, len, false); + if (err != OK) { + return PackedByteArray(); + } + + PackedByteArray barr; + barr.resize(len); + { + uint8_t *w = barr.ptrw(); + err = encode_variant(p_var, w, len, false); + if (err != OK) { + return PackedByteArray(); + } + } + + return barr; + } + + static inline PackedByteArray var2bytes_with_objects(const Variant &p_var) { + int len; + Error err = encode_variant(p_var, nullptr, len, true); + if (err != OK) { + return PackedByteArray(); + } + + PackedByteArray barr; + barr.resize(len); + { + uint8_t *w = barr.ptrw(); + err = encode_variant(p_var, w, len, true); + if (err != OK) { + return PackedByteArray(); + } + } + + return barr; + } + + static inline Variant bytes2var(const PackedByteArray &p_arr) { + Variant ret; + { + const uint8_t *r = p_arr.ptr(); + Error err = decode_variant(ret, r, p_arr.size(), nullptr, false); + if (err != OK) { + return Variant(); + } + } + return ret; + } + + static inline Variant bytes2var_with_objects(const PackedByteArray &p_arr) { + Variant ret; + { + const uint8_t *r = p_arr.ptr(); + Error err = decode_variant(ret, r, p_arr.size(), nullptr, true); + if (err != OK) { + return Variant(); + } + } + return ret; + } + + static inline int64_t hash(const Variant &p_arr) { + return p_arr.hash(); + } + + static inline Object *instance_from_id(int64_t p_id) { + ObjectID id = ObjectID((uint64_t)p_id); + Object *ret = ObjectDB::get_instance(id); + return ret; + } + + static inline bool is_instance_id_valid(int64_t p_id) { + return ObjectDB::get_instance(ObjectID((uint64_t)p_id)) != nullptr; + } + + static inline bool is_instance_valid(const Variant &p_instance) { + if (p_instance.get_type() != Variant::OBJECT) { + return false; + } + return p_instance.get_validated_object() != nullptr; + } +}; + +#ifdef DEBUG_METHODS_ENABLED +#define VCALLR *ret = p_func(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...) +#define VCALL p_func(VariantCasterAndValidate<P>::cast(p_args, Is, r_error)...) +#else +#define VCALLR *ret = p_func(VariantCaster<P>::cast(*p_args[Is])...) +#define VCALL p_func(VariantCaster<P>::cast(*p_args[Is])...) +#endif + +template <class R, class... P, size_t... Is> +static _FORCE_INLINE_ void call_helperpr(R (*p_func)(P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) { + r_error.error = Callable::CallError::CALL_OK; + VCALLR; + (void)p_args; // avoid gcc warning + (void)r_error; +} + +template <class R, class... P, size_t... Is> +static _FORCE_INLINE_ void validated_call_helperpr(R (*p_func)(P...), Variant *ret, const Variant **p_args, IndexSequence<Is...>) { + *ret = p_func(VariantCaster<P>::cast(*p_args[Is])...); + (void)p_args; +} + +template <class R, class... P, size_t... Is> +static _FORCE_INLINE_ void ptr_call_helperpr(R (*p_func)(P...), void *ret, const void **p_args, IndexSequence<Is...>) { + PtrToArg<R>::encode(p_func(PtrToArg<P>::convert(p_args[Is])...), ret); + (void)p_args; +} + +template <class R, class... P> +static _FORCE_INLINE_ void call_helperr(R (*p_func)(P...), Variant *ret, const Variant **p_args, Callable::CallError &r_error) { + call_helperpr(p_func, ret, p_args, r_error, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class R, class... P> +static _FORCE_INLINE_ void validated_call_helperr(R (*p_func)(P...), Variant *ret, const Variant **p_args) { + validated_call_helperpr(p_func, ret, p_args, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class R, class... P> +static _FORCE_INLINE_ void ptr_call_helperr(R (*p_func)(P...), void *ret, const void **p_args) { + ptr_call_helperpr(p_func, ret, p_args, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class R, class... P> +static _FORCE_INLINE_ int get_arg_count_helperr(R (*p_func)(P...)) { + return sizeof...(P); +} + +template <class R, class... P> +static _FORCE_INLINE_ Variant::Type get_arg_type_helperr(R (*p_func)(P...), int p_arg) { + return call_get_argument_type<P...>(p_arg); +} + +template <class R, class... P> +static _FORCE_INLINE_ Variant::Type get_ret_type_helperr(R (*p_func)(P...)) { + return GetTypeInfo<R>::VARIANT_TYPE; +} + +// WITHOUT RET + +template <class... P, size_t... Is> +static _FORCE_INLINE_ void call_helperp(void (*p_func)(P...), const Variant **p_args, Callable::CallError &r_error, IndexSequence<Is...>) { + r_error.error = Callable::CallError::CALL_OK; + VCALL; + (void)p_args; + (void)r_error; +} + +template <class... P, size_t... Is> +static _FORCE_INLINE_ void validated_call_helperp(void (*p_func)(P...), const Variant **p_args, IndexSequence<Is...>) { + p_func(VariantCaster<P>::cast(*p_args[Is])...); + (void)p_args; +} + +template <class... P, size_t... Is> +static _FORCE_INLINE_ void ptr_call_helperp(void (*p_func)(P...), const void **p_args, IndexSequence<Is...>) { + p_func(PtrToArg<P>::convert(p_args[Is])...); + (void)p_args; +} + +template <class... P> +static _FORCE_INLINE_ void call_helper(void (*p_func)(P...), const Variant **p_args, Callable::CallError &r_error) { + call_helperp(p_func, p_args, r_error, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class... P> +static _FORCE_INLINE_ void validated_call_helper(void (*p_func)(P...), const Variant **p_args) { + validated_call_helperp(p_func, p_args, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class... P> +static _FORCE_INLINE_ void ptr_call_helper(void (*p_func)(P...), const void **p_args) { + ptr_call_helperp(p_func, p_args, BuildIndexSequence<sizeof...(P)>{}); +} + +template <class... P> +static _FORCE_INLINE_ int get_arg_count_helper(void (*p_func)(P...)) { + return sizeof...(P); +} + +template <class... P> +static _FORCE_INLINE_ Variant::Type get_arg_type_helper(void (*p_func)(P...), int p_arg) { + return call_get_argument_type<P...>(p_arg); +} + +template <class... P> +static _FORCE_INLINE_ Variant::Type get_ret_type_helper(void (*p_func)(P...)) { + return Variant::NIL; +} + +#define FUNCBINDR(m_func, m_args, m_category) \ + class Func_##m_func { \ + public: \ + static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ + call_helperr(VariantUtilityFunctions::m_func, r_ret, p_args, r_error); \ + } \ + static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ + validated_call_helperr(VariantUtilityFunctions::m_func, r_ret, p_args); \ + } \ + static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ + ptr_call_helperr(VariantUtilityFunctions::m_func, ret, p_args); \ + } \ + static int get_argument_count() { \ + return get_arg_count_helperr(VariantUtilityFunctions::m_func); \ + } \ + static Variant::Type get_argument_type(int p_arg) { \ + return get_arg_type_helperr(VariantUtilityFunctions::m_func, p_arg); \ + } \ + static Variant::Type get_return_type() { \ + return get_ret_type_helperr(VariantUtilityFunctions::m_func); \ + } \ + static bool has_return_type() { \ + return true; \ + } \ + static bool is_vararg() { return false; } \ + static Variant::UtilityFunctionType get_type() { return m_category; } \ + }; \ + register_utility_function<Func_##m_func>(#m_func, m_args) + +#define FUNCBINDVR(m_func, m_args, m_category) \ + class Func_##m_func { \ + public: \ + static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ + r_error.error = Callable::CallError::CALL_OK; \ + *r_ret = VariantUtilityFunctions::m_func(*p_args[0], r_error); \ + } \ + static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ + Callable::CallError ce; \ + *r_ret = VariantUtilityFunctions::m_func(*p_args[0], ce); \ + } \ + static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ + Callable::CallError ce; \ + PtrToArg<Variant>::encode(VariantUtilityFunctions::m_func(PtrToArg<Variant>::convert(p_args[0]), ce), ret); \ + } \ + static int get_argument_count() { \ + return 1; \ + } \ + static Variant::Type get_argument_type(int p_arg) { \ + return Variant::NIL; \ + } \ + static Variant::Type get_return_type() { \ + return Variant::NIL; \ + } \ + static bool has_return_type() { \ + return true; \ + } \ + static bool is_vararg() { return false; } \ + static Variant::UtilityFunctionType get_type() { return m_category; } \ + }; \ + register_utility_function<Func_##m_func>(#m_func, m_args) + +#define FUNCBINDVR3(m_func, m_args, m_category) \ + class Func_##m_func { \ + public: \ + static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ + r_error.error = Callable::CallError::CALL_OK; \ + *r_ret = VariantUtilityFunctions::m_func(*p_args[0], *p_args[1], *p_args[2], r_error); \ + } \ + static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ + Callable::CallError ce; \ + *r_ret = VariantUtilityFunctions::m_func(*p_args[0], *p_args[1], *p_args[2], ce); \ + } \ + static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ + Callable::CallError ce; \ + Variant r; \ + r = VariantUtilityFunctions::m_func(PtrToArg<Variant>::convert(p_args[0]), PtrToArg<Variant>::convert(p_args[1]), PtrToArg<Variant>::convert(p_args[2]), ce); \ + PtrToArg<Variant>::encode(r, ret); \ + } \ + static int get_argument_count() { \ + return 3; \ + } \ + static Variant::Type get_argument_type(int p_arg) { \ + return Variant::NIL; \ + } \ + static Variant::Type get_return_type() { \ + return Variant::NIL; \ + } \ + static bool has_return_type() { \ + return true; \ + } \ + static bool is_vararg() { return false; } \ + static Variant::UtilityFunctionType get_type() { return m_category; } \ + }; \ + register_utility_function<Func_##m_func>(#m_func, m_args) + +#define FUNCBINDVARARG(m_func, m_args, m_category) \ + class Func_##m_func { \ + public: \ + static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ + r_error.error = Callable::CallError::CALL_OK; \ + *r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, r_error); \ + } \ + static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ + Callable::CallError c; \ + *r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, c); \ + } \ + static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ + Vector<Variant> args; \ + for (int i = 0; i < p_argcount; i++) { \ + args.push_back(PtrToArg<Variant>::convert(p_args[i])); \ + } \ + Vector<const Variant *> argsp; \ + for (int i = 0; i < p_argcount; i++) { \ + argsp.push_back(&args[i]); \ + } \ + Variant r; \ + validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); \ + PtrToArg<Variant>::encode(r, ret); \ + } \ + static int get_argument_count() { \ + return 2; \ + } \ + static Variant::Type get_argument_type(int p_arg) { \ + return Variant::NIL; \ + } \ + static Variant::Type get_return_type() { \ + return Variant::NIL; \ + } \ + static bool has_return_type() { \ + return true; \ + } \ + static bool is_vararg() { \ + return true; \ + } \ + static Variant::UtilityFunctionType get_type() { \ + return m_category; \ + } \ + }; \ + register_utility_function<Func_##m_func>(#m_func, m_args) + +#define FUNCBINDVARARGS(m_func, m_args, m_category) \ + class Func_##m_func { \ + public: \ + static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ + r_error.error = Callable::CallError::CALL_OK; \ + *r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, r_error); \ + } \ + static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ + Callable::CallError c; \ + *r_ret = VariantUtilityFunctions::m_func(p_args, p_argcount, c); \ + } \ + static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ + Vector<Variant> args; \ + for (int i = 0; i < p_argcount; i++) { \ + args.push_back(PtrToArg<Variant>::convert(p_args[i])); \ + } \ + Vector<const Variant *> argsp; \ + for (int i = 0; i < p_argcount; i++) { \ + argsp.push_back(&args[i]); \ + } \ + Variant r; \ + validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); \ + PtrToArg<String>::encode(r.operator String(), ret); \ + } \ + static int get_argument_count() { \ + return 1; \ + } \ + static Variant::Type get_argument_type(int p_arg) { \ + return Variant::NIL; \ + } \ + static Variant::Type get_return_type() { \ + return Variant::STRING; \ + } \ + static bool has_return_type() { \ + return true; \ + } \ + static bool is_vararg() { \ + return true; \ + } \ + static Variant::UtilityFunctionType get_type() { \ + return m_category; \ + } \ + }; \ + register_utility_function<Func_##m_func>(#m_func, m_args) + +#define FUNCBINDVARARGV(m_func, m_args, m_category) \ + class Func_##m_func { \ + public: \ + static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ + r_error.error = Callable::CallError::CALL_OK; \ + VariantUtilityFunctions::m_func(p_args, p_argcount, r_error); \ + } \ + static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ + Callable::CallError c; \ + VariantUtilityFunctions::m_func(p_args, p_argcount, c); \ + } \ + static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ + Vector<Variant> args; \ + for (int i = 0; i < p_argcount; i++) { \ + args.push_back(PtrToArg<Variant>::convert(p_args[i])); \ + } \ + Vector<const Variant *> argsp; \ + for (int i = 0; i < p_argcount; i++) { \ + argsp.push_back(&args[i]); \ + } \ + Variant r; \ + validated_call(&r, (const Variant **)argsp.ptr(), p_argcount); \ + } \ + static int get_argument_count() { \ + return 1; \ + } \ + static Variant::Type get_argument_type(int p_arg) { \ + return Variant::NIL; \ + } \ + static Variant::Type get_return_type() { \ + return Variant::NIL; \ + } \ + static bool has_return_type() { \ + return false; \ + } \ + static bool is_vararg() { \ + return true; \ + } \ + static Variant::UtilityFunctionType get_type() { \ + return m_category; \ + } \ + }; \ + register_utility_function<Func_##m_func>(#m_func, m_args) + +#define FUNCBIND(m_func, m_args, m_category) \ + class Func_##m_func { \ + public: \ + static void call(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { \ + call_helper(VariantUtilityFunctions::m_func, p_args, r_error); \ + } \ + static void validated_call(Variant *r_ret, const Variant **p_args, int p_argcount) { \ + validated_call_helper(VariantUtilityFunctions::m_func, p_args); \ + } \ + static void ptrcall(void *ret, const void **p_args, int p_argcount) { \ + ptr_call_helper(VariantUtilityFunctions::m_func, p_args); \ + } \ + static int get_argument_count() { \ + return get_arg_count_helper(VariantUtilityFunctions::m_func); \ + } \ + static Variant::Type get_argument_type(int p_arg) { \ + return get_arg_type_helper(VariantUtilityFunctions::m_func, p_arg); \ + } \ + static Variant::Type get_return_type() { \ + return get_ret_type_helper(VariantUtilityFunctions::m_func); \ + } \ + static bool has_return_type() { \ + return false; \ + } \ + static bool is_vararg() { return false; } \ + static Variant::UtilityFunctionType get_type() { return m_category; } \ + }; \ + register_utility_function<Func_##m_func>(#m_func, m_args) + +struct VariantUtilityFunctionInfo { + void (*call_utility)(Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error); + Variant::ValidatedUtilityFunction validated_call_utility; + Variant::PTRUtilityFunction ptr_call_utility; + Vector<String> argnames; + bool is_vararg; + bool returns_value; + int argcount; + Variant::Type (*get_arg_type)(int); + Variant::Type return_type; + Variant::UtilityFunctionType type; +}; + +static OAHashMap<StringName, VariantUtilityFunctionInfo> utility_function_table; +static List<StringName> utility_function_name_table; + +template <class T> +static void register_utility_function(const String &p_name, const Vector<String> &argnames) { + String name = p_name; + if (name.begins_with("_")) { + name = name.substr(1, name.length() - 1); + } + StringName sname = name; + ERR_FAIL_COND(utility_function_table.has(sname)); + + VariantUtilityFunctionInfo bfi; + bfi.call_utility = T::call; + bfi.validated_call_utility = T::validated_call; + bfi.ptr_call_utility = T::ptrcall; + bfi.is_vararg = T::is_vararg(); + bfi.argnames = argnames; + bfi.argcount = T::get_argument_count(); + if (!bfi.is_vararg) { + ERR_FAIL_COND_MSG(argnames.size() != bfi.argcount, "wrong number of arguments binding utility function: " + name); + } + bfi.get_arg_type = T::get_argument_type; + bfi.return_type = T::get_return_type(); + bfi.type = T::get_type(); + bfi.returns_value = T::has_return_type(); + + utility_function_table.insert(sname, bfi); + utility_function_name_table.push_back(sname); +} + +void Variant::_register_variant_utility_functions() { + // Math + + FUNCBINDR(sin, sarray("angle_rad"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(cos, sarray("angle_rad"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(tan, sarray("angle_rad"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(sinh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(cosh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(tanh, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(asin, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(acos, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(atan, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(atan2, sarray("y", "x"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(sqrt, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(fmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(fposmod, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(floor, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(ceil, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(round, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDVR(abs, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(absf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(absi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDVR(sign, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(signf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(signi, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(pow, sarray("base", "exp"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(log, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(exp, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(is_nan, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(is_inf, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(is_equal_approx, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(is_zero_approx, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(ease, sarray("x", "curve"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(step_decimals, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(range_step_decimals, sarray("x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(snapped, sarray("x", "step"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(lerp_angle, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(inverse_lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(range_lerp, sarray("value", "istart", "istop", "ostart", "ostop"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(smoothstep, sarray("from", "to", "x"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(move_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(dectime, sarray("value", "amount", "step"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(deg2rad, sarray("deg"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(rad2deg, sarray("rad"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(linear2db, sarray("lin"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(db2linear, sarray("db"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(polar2cartesian, sarray("r", "th"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(cartesian2polar, sarray("x", "y"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(wrapi, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(wrapf, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDVARARG(max, sarray(), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(maxi, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(maxf, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDVARARG(min, sarray(), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(mini, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(minf, sarray("a", "b"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDVR3(clamp, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(clampi, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(clampf, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); + + FUNCBINDR(nearest_po2, sarray("value"), Variant::UTILITY_FUNC_TYPE_MATH); + + // Random + + FUNCBIND(randomize, sarray(), Variant::UTILITY_FUNC_TYPE_RANDOM); + FUNCBINDR(randi, sarray(), Variant::UTILITY_FUNC_TYPE_RANDOM); + FUNCBINDR(randf, sarray(), Variant::UTILITY_FUNC_TYPE_RANDOM); + FUNCBINDR(randi_range, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_RANDOM); + FUNCBINDR(randf_range, sarray("from", "to"), Variant::UTILITY_FUNC_TYPE_RANDOM); + FUNCBIND(seed, sarray("base"), Variant::UTILITY_FUNC_TYPE_RANDOM); + FUNCBINDR(rand_from_seed, sarray("seed"), Variant::UTILITY_FUNC_TYPE_RANDOM); + + // Utility + + FUNCBINDVR(weakref, sarray("obj"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(_typeof, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDVARARGS(str, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDVARARGV(print, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDVARARGV(printerr, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDVARARGV(printt, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDVARARGV(prints, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDVARARGV(printraw, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDVARARGV(push_error, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDVARARGV(push_warning, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); + + FUNCBINDR(var2str, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(str2var, sarray("string"), Variant::UTILITY_FUNC_TYPE_GENERAL); + + FUNCBINDR(var2bytes, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(bytes2var, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL); + + FUNCBINDR(var2bytes_with_objects, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(bytes2var_with_objects, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL); + + FUNCBINDR(hash, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); + + FUNCBINDR(instance_from_id, sarray("instance_id"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(is_instance_id_valid, sarray("id"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(is_instance_valid, sarray("instance"), Variant::UTILITY_FUNC_TYPE_GENERAL); +} + +void Variant::_unregister_variant_utility_functions() { + utility_function_table.clear(); + utility_function_name_table.clear(); +} + +void Variant::call_utility_function(const StringName &p_name, Variant *r_ret, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); + if (!bfi) { + r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; + r_error.argument = 0; + r_error.expected = 0; + return; + } + + if (unlikely(!bfi->is_vararg && p_argcount < bfi->argcount)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; + r_error.argument = 0; + r_error.expected = bfi->argcount; + return; + } + + if (unlikely(!bfi->is_vararg && p_argcount > bfi->argcount)) { + r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; + r_error.argument = 0; + r_error.expected = bfi->argcount; + return; + } + + bfi->call_utility(r_ret, p_args, p_argcount, r_error); +} + +bool Variant::has_utility_function(const StringName &p_name) { + return utility_function_table.has(p_name); +} + +Variant::ValidatedUtilityFunction Variant::get_validated_utility_function(const StringName &p_name) { + const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); + if (!bfi) { + return nullptr; + } + + return bfi->validated_call_utility; +} + +Variant::PTRUtilityFunction Variant::get_ptr_utility_function(const StringName &p_name) { + const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); + if (!bfi) { + return nullptr; + } + + return bfi->ptr_call_utility; +} + +Variant::UtilityFunctionType Variant::get_utility_function_type(const StringName &p_name) { + const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); + if (!bfi) { + return Variant::UTILITY_FUNC_TYPE_MATH; + } + + return bfi->type; +} + +int Variant::get_utility_function_argument_count(const StringName &p_name) { + const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); + if (!bfi) { + return 0; + } + + return bfi->argcount; +} + +Variant::Type Variant::get_utility_function_argument_type(const StringName &p_name, int p_arg) { + const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); + if (!bfi) { + return Variant::NIL; + } + + return bfi->get_arg_type(p_arg); +} + +String Variant::get_utility_function_argument_name(const StringName &p_name, int p_arg) { + const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); + if (!bfi) { + return String(); + } + ERR_FAIL_COND_V(bfi->is_vararg, String()); + ERR_FAIL_INDEX_V(p_arg, bfi->argnames.size(), String()); + return bfi->argnames[p_arg]; +} + +bool Variant::has_utility_function_return_value(const StringName &p_name) { + const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); + if (!bfi) { + return false; + } + return bfi->returns_value; +} + +Variant::Type Variant::get_utility_function_return_type(const StringName &p_name) { + const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); + if (!bfi) { + return Variant::NIL; + } + + return bfi->return_type; +} + +bool Variant::is_utility_function_vararg(const StringName &p_name) { + const VariantUtilityFunctionInfo *bfi = utility_function_table.lookup_ptr(p_name); + if (!bfi) { + return false; + } + + return bfi->is_vararg; +} + +void Variant::get_utility_function_list(List<StringName> *r_functions) { + for (List<StringName>::Element *E = utility_function_name_table.front(); E; E = E->next()) { + r_functions->push_back(E->get()); + } +} + +int Variant::get_utility_function_count() { + return utility_function_name_table.size(); +} diff --git a/core/variant_call.cpp b/core/variant_call.cpp deleted file mode 100644 index 6ee63e1610..0000000000 --- a/core/variant_call.cpp +++ /dev/null @@ -1,2512 +0,0 @@ -/*************************************************************************/ -/* variant_call.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "variant.h" - -#include "core/color_names.inc" -#include "core/core_string_names.h" -#include "core/crypto/crypto_core.h" -#include "core/debugger/engine_debugger.h" -#include "core/io/compression.h" -#include "core/object.h" -#include "core/os/os.h" - -typedef void (*VariantFunc)(Variant &r_ret, Variant &p_self, const Variant **p_args); -typedef void (*VariantConstructFunc)(Variant &r_ret, const Variant **p_args); - -struct _VariantCall { - static void Vector3_dot(Variant &r_ret, Variant &p_self, const Variant **p_args) { - r_ret = reinterpret_cast<Vector3 *>(p_self._data._mem)->dot(*reinterpret_cast<const Vector3 *>(p_args[0]->_data._mem)); - } - - struct FuncData { - int arg_count; - Vector<Variant> default_args; - Vector<Variant::Type> arg_types; - Vector<StringName> arg_names; - Variant::Type return_type; - - bool _const; - bool returns; - - VariantFunc func; - - _FORCE_INLINE_ bool verify_arguments(const Variant **p_args, Callable::CallError &r_error) { - if (arg_count == 0) { - return true; - } - - const Variant::Type *tptr = &arg_types[0]; - - for (int i = 0; i < arg_count; i++) { - if (tptr[i] == Variant::NIL || tptr[i] == p_args[i]->type) { - continue; // all good - } - if (!Variant::can_convert(p_args[i]->type, tptr[i])) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = i; - r_error.expected = tptr[i]; - return false; - } - } - return true; - } - - _FORCE_INLINE_ void call(Variant &r_ret, Variant &p_self, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { -#ifdef DEBUG_ENABLED - if (p_argcount > arg_count) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS; - r_error.argument = arg_count; - return; - } else -#endif - if (p_argcount < arg_count) { - int def_argcount = default_args.size(); -#ifdef DEBUG_ENABLED - if (p_argcount < (arg_count - def_argcount)) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = arg_count - def_argcount; - return; - } - -#endif - ERR_FAIL_COND(p_argcount > VARIANT_ARG_MAX); - const Variant *newargs[VARIANT_ARG_MAX]; - for (int i = 0; i < p_argcount; i++) { - newargs[i] = p_args[i]; - } - // fill in any remaining parameters with defaults - int first_default_arg = arg_count - def_argcount; - for (int i = p_argcount; i < arg_count; i++) { - newargs[i] = &default_args[i - first_default_arg]; - } -#ifdef DEBUG_ENABLED - if (!verify_arguments(newargs, r_error)) { - return; - } -#endif - func(r_ret, p_self, newargs); - } else { -#ifdef DEBUG_ENABLED - if (!verify_arguments(p_args, r_error)) { - return; - } -#endif - func(r_ret, p_self, p_args); - } - } - }; - - struct TypeFunc { - Map<StringName, FuncData> functions; - }; - - static TypeFunc *type_funcs; - - struct Arg { - StringName name; - Variant::Type type; - Arg() { type = Variant::NIL; } - Arg(Variant::Type p_type, const StringName &p_name) : - name(p_name), - type(p_type) { - } - }; - - //void addfunc(Variant::Type p_type, const StringName& p_name,VariantFunc p_func); - - static void make_func_return_variant(Variant::Type p_type, const StringName &p_name) { -#ifdef DEBUG_ENABLED - type_funcs[p_type].functions[p_name].returns = true; -#endif - } - - static void addfunc(bool p_const, Variant::Type p_type, Variant::Type p_return, bool p_has_return, const StringName &p_name, VariantFunc p_func, const Vector<Variant> &p_defaultarg, const Arg &p_argtype1 = Arg(), const Arg &p_argtype2 = Arg(), const Arg &p_argtype3 = Arg(), const Arg &p_argtype4 = Arg(), const Arg &p_argtype5 = Arg()) { - FuncData funcdata; - funcdata.func = p_func; - funcdata.default_args = p_defaultarg; - funcdata._const = p_const; - funcdata.returns = p_has_return; - funcdata.return_type = p_return; - - if (p_argtype1.name) { - funcdata.arg_types.push_back(p_argtype1.type); -#ifdef DEBUG_ENABLED - funcdata.arg_names.push_back(p_argtype1.name); -#endif - - } else { - goto end; - } - - if (p_argtype2.name) { - funcdata.arg_types.push_back(p_argtype2.type); -#ifdef DEBUG_ENABLED - funcdata.arg_names.push_back(p_argtype2.name); -#endif - - } else { - goto end; - } - - if (p_argtype3.name) { - funcdata.arg_types.push_back(p_argtype3.type); -#ifdef DEBUG_ENABLED - funcdata.arg_names.push_back(p_argtype3.name); -#endif - - } else { - goto end; - } - - if (p_argtype4.name) { - funcdata.arg_types.push_back(p_argtype4.type); -#ifdef DEBUG_ENABLED - funcdata.arg_names.push_back(p_argtype4.name); -#endif - } else { - goto end; - } - - if (p_argtype5.name) { - funcdata.arg_types.push_back(p_argtype5.type); -#ifdef DEBUG_ENABLED - funcdata.arg_names.push_back(p_argtype5.name); -#endif - } else { - goto end; - } - - end: - - funcdata.arg_count = funcdata.arg_types.size(); - type_funcs[p_type].functions[p_name] = funcdata; - } - -#define VCALL_LOCALMEM0(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._mem)->m_method(); } -#define VCALL_LOCALMEM0R(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast<m_type *>(p_self._data._mem)->m_method(); } -#define VCALL_LOCALMEM1(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._mem)->m_method(*p_args[0]); } -#define VCALL_LOCALMEM1R(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast<m_type *>(p_self._data._mem)->m_method(*p_args[0]); } -#define VCALL_LOCALMEM2(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._mem)->m_method(*p_args[0], *p_args[1]); } -#define VCALL_LOCALMEM2R(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast<m_type *>(p_self._data._mem)->m_method(*p_args[0], *p_args[1]); } -#define VCALL_LOCALMEM3(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._mem)->m_method(*p_args[0], *p_args[1], *p_args[2]); } -#define VCALL_LOCALMEM3R(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast<m_type *>(p_self._data._mem)->m_method(*p_args[0], *p_args[1], *p_args[2]); } -#define VCALL_LOCALMEM4(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._mem)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); } -#define VCALL_LOCALMEM4R(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast<m_type *>(p_self._data._mem)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); } -#define VCALL_LOCALMEM5(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._mem)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3], *p_args[4]); } -#define VCALL_LOCALMEM5R(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast<m_type *>(p_self._data._mem)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3], *p_args[4]); } - - // built-in functions of localmem based types - - VCALL_LOCALMEM1R(String, casecmp_to); - VCALL_LOCALMEM1R(String, nocasecmp_to); - VCALL_LOCALMEM1R(String, naturalnocasecmp_to); - VCALL_LOCALMEM0R(String, length); - VCALL_LOCALMEM3R(String, count); - VCALL_LOCALMEM3R(String, countn); - VCALL_LOCALMEM2R(String, substr); - VCALL_LOCALMEM2R(String, find); - VCALL_LOCALMEM2R(String, findn); - VCALL_LOCALMEM2R(String, rfind); - VCALL_LOCALMEM2R(String, rfindn); - VCALL_LOCALMEM1R(String, match); - VCALL_LOCALMEM1R(String, matchn); - VCALL_LOCALMEM1R(String, begins_with); - VCALL_LOCALMEM1R(String, ends_with); - VCALL_LOCALMEM1R(String, is_subsequence_of); - VCALL_LOCALMEM1R(String, is_subsequence_ofi); - VCALL_LOCALMEM0R(String, bigrams); - VCALL_LOCALMEM1R(String, similarity); - VCALL_LOCALMEM2R(String, format); - VCALL_LOCALMEM2R(String, replace); - VCALL_LOCALMEM2R(String, replacen); - VCALL_LOCALMEM1R(String, repeat); - VCALL_LOCALMEM2R(String, insert); - VCALL_LOCALMEM0R(String, capitalize); - VCALL_LOCALMEM3R(String, split); - VCALL_LOCALMEM3R(String, rsplit); - VCALL_LOCALMEM2R(String, split_floats); - VCALL_LOCALMEM1R(String, join); - VCALL_LOCALMEM0R(String, to_upper); - VCALL_LOCALMEM0R(String, to_lower); - VCALL_LOCALMEM1R(String, left); - VCALL_LOCALMEM1R(String, right); - VCALL_LOCALMEM0R(String, dedent); - VCALL_LOCALMEM2R(String, strip_edges); - VCALL_LOCALMEM0R(String, strip_escapes); - VCALL_LOCALMEM1R(String, lstrip); - VCALL_LOCALMEM1R(String, rstrip); - VCALL_LOCALMEM0R(String, get_extension); - VCALL_LOCALMEM0R(String, get_basename); - VCALL_LOCALMEM1R(String, plus_file); - VCALL_LOCALMEM1R(String, ord_at); - VCALL_LOCALMEM2(String, erase); - VCALL_LOCALMEM0R(String, hash); - VCALL_LOCALMEM0R(String, md5_text); - VCALL_LOCALMEM0R(String, sha1_text); - VCALL_LOCALMEM0R(String, sha256_text); - VCALL_LOCALMEM0R(String, md5_buffer); - VCALL_LOCALMEM0R(String, sha1_buffer); - VCALL_LOCALMEM0R(String, sha256_buffer); - VCALL_LOCALMEM0R(String, empty); - VCALL_LOCALMEM1R(String, humanize_size); - VCALL_LOCALMEM0R(String, is_abs_path); - VCALL_LOCALMEM0R(String, is_rel_path); - VCALL_LOCALMEM0R(String, get_base_dir); - VCALL_LOCALMEM0R(String, get_file); - VCALL_LOCALMEM0R(String, xml_escape); - VCALL_LOCALMEM0R(String, xml_unescape); - VCALL_LOCALMEM0R(String, http_escape); - VCALL_LOCALMEM0R(String, http_unescape); - VCALL_LOCALMEM0R(String, c_escape); - VCALL_LOCALMEM0R(String, c_unescape); - VCALL_LOCALMEM0R(String, json_escape); - VCALL_LOCALMEM0R(String, percent_encode); - VCALL_LOCALMEM0R(String, percent_decode); - VCALL_LOCALMEM0R(String, is_valid_identifier); - VCALL_LOCALMEM0R(String, is_valid_integer); - VCALL_LOCALMEM0R(String, is_valid_float); - VCALL_LOCALMEM1R(String, is_valid_hex_number); - VCALL_LOCALMEM0R(String, is_valid_html_color); - VCALL_LOCALMEM0R(String, is_valid_ip_address); - VCALL_LOCALMEM0R(String, is_valid_filename); - VCALL_LOCALMEM0R(String, to_int); - VCALL_LOCALMEM0R(String, to_float); - VCALL_LOCALMEM0R(String, hex_to_int); - VCALL_LOCALMEM2R(String, lpad); - VCALL_LOCALMEM2R(String, rpad); - VCALL_LOCALMEM1R(String, pad_decimals); - VCALL_LOCALMEM1R(String, pad_zeros); - VCALL_LOCALMEM1R(String, trim_prefix); - VCALL_LOCALMEM1R(String, trim_suffix); - - static void _call_String_to_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) { - String *s = reinterpret_cast<String *>(p_self._data._mem); - if (s->empty()) { - r_ret = PackedByteArray(); - return; - } - CharString charstr = s->ascii(); - - PackedByteArray retval; - size_t len = charstr.length(); - retval.resize(len); - uint8_t *w = retval.ptrw(); - copymem(w, charstr.ptr(), len); - - r_ret = retval; - } - - static void _call_String_to_utf8(Variant &r_ret, Variant &p_self, const Variant **p_args) { - String *s = reinterpret_cast<String *>(p_self._data._mem); - if (s->empty()) { - r_ret = PackedByteArray(); - return; - } - CharString charstr = s->utf8(); - - PackedByteArray retval; - size_t len = charstr.length(); - retval.resize(len); - uint8_t *w = retval.ptrw(); - copymem(w, charstr.ptr(), len); - - r_ret = retval; - } - - static void _call_String_to_utf16(Variant &r_ret, Variant &p_self, const Variant **p_args) { - String *s = reinterpret_cast<String *>(p_self._data._mem); - if (s->empty()) { - r_ret = PackedByteArray(); - return; - } - Char16String charstr = s->utf16(); - - PackedByteArray retval; - size_t len = charstr.length() * 2; - retval.resize(len); - uint8_t *w = retval.ptrw(); - copymem(w, (const void *)charstr.ptr(), len); - - r_ret = retval; - } - - static void _call_String_to_utf32(Variant &r_ret, Variant &p_self, const Variant **p_args) { - String *s = reinterpret_cast<String *>(p_self._data._mem); - if (s->empty()) { - r_ret = PackedByteArray(); - return; - } - - PackedByteArray retval; - size_t len = s->length() * 4; - retval.resize(len); - uint8_t *w = retval.ptrw(); - copymem(w, (const void *)s->ptr(), len); - - r_ret = retval; - } - - VCALL_LOCALMEM1R(Vector2, distance_to); - VCALL_LOCALMEM1R(Vector2, distance_squared_to); - VCALL_LOCALMEM0R(Vector2, length); - VCALL_LOCALMEM0R(Vector2, length_squared); - VCALL_LOCALMEM0R(Vector2, normalized); - VCALL_LOCALMEM0R(Vector2, is_normalized); - VCALL_LOCALMEM1R(Vector2, is_equal_approx); - VCALL_LOCALMEM1R(Vector2, posmod); - VCALL_LOCALMEM1R(Vector2, posmodv); - VCALL_LOCALMEM1R(Vector2, project); - VCALL_LOCALMEM1R(Vector2, angle_to); - VCALL_LOCALMEM1R(Vector2, angle_to_point); - VCALL_LOCALMEM1R(Vector2, direction_to); - VCALL_LOCALMEM2R(Vector2, lerp); - VCALL_LOCALMEM2R(Vector2, slerp); - VCALL_LOCALMEM4R(Vector2, cubic_interpolate); - VCALL_LOCALMEM2R(Vector2, move_toward); - VCALL_LOCALMEM1R(Vector2, rotated); - VCALL_LOCALMEM0R(Vector2, tangent); - VCALL_LOCALMEM0R(Vector2, floor); - VCALL_LOCALMEM0R(Vector2, ceil); - VCALL_LOCALMEM0R(Vector2, round); - VCALL_LOCALMEM1R(Vector2, snapped); - VCALL_LOCALMEM0R(Vector2, aspect); - VCALL_LOCALMEM1R(Vector2, dot); - VCALL_LOCALMEM1R(Vector2, slide); - VCALL_LOCALMEM1R(Vector2, bounce); - VCALL_LOCALMEM1R(Vector2, reflect); - VCALL_LOCALMEM0R(Vector2, angle); - VCALL_LOCALMEM1R(Vector2, cross); - VCALL_LOCALMEM0R(Vector2, abs); - VCALL_LOCALMEM1R(Vector2, clamped); - VCALL_LOCALMEM0R(Vector2, sign); - - VCALL_LOCALMEM0R(Vector2i, aspect); - VCALL_LOCALMEM0R(Vector2i, sign); - VCALL_LOCALMEM0R(Vector2i, abs); - - VCALL_LOCALMEM0R(Rect2, get_area); - VCALL_LOCALMEM0R(Rect2, has_no_area); - VCALL_LOCALMEM1R(Rect2, has_point); - VCALL_LOCALMEM1R(Rect2, is_equal_approx); - VCALL_LOCALMEM2R(Rect2, intersects); - VCALL_LOCALMEM1R(Rect2, encloses); - VCALL_LOCALMEM1R(Rect2, clip); - VCALL_LOCALMEM1R(Rect2, merge); - VCALL_LOCALMEM1R(Rect2, expand); - VCALL_LOCALMEM1R(Rect2, grow); - VCALL_LOCALMEM2R(Rect2, grow_margin); - VCALL_LOCALMEM4R(Rect2, grow_individual); - VCALL_LOCALMEM0R(Rect2, abs); - - VCALL_LOCALMEM0R(Rect2i, get_area); - VCALL_LOCALMEM0R(Rect2i, has_no_area); - VCALL_LOCALMEM1R(Rect2i, has_point); - VCALL_LOCALMEM1R(Rect2i, intersects); - VCALL_LOCALMEM1R(Rect2i, encloses); - VCALL_LOCALMEM1R(Rect2i, clip); - VCALL_LOCALMEM1R(Rect2i, merge); - VCALL_LOCALMEM1R(Rect2i, expand); - VCALL_LOCALMEM1R(Rect2i, grow); - VCALL_LOCALMEM2R(Rect2i, grow_margin); - VCALL_LOCALMEM4R(Rect2i, grow_individual); - VCALL_LOCALMEM0R(Rect2i, abs); - - VCALL_LOCALMEM0R(Vector3, min_axis); - VCALL_LOCALMEM0R(Vector3, max_axis); - VCALL_LOCALMEM1R(Vector3, distance_to); - VCALL_LOCALMEM1R(Vector3, distance_squared_to); - VCALL_LOCALMEM0R(Vector3, length); - VCALL_LOCALMEM0R(Vector3, length_squared); - VCALL_LOCALMEM0R(Vector3, normalized); - VCALL_LOCALMEM0R(Vector3, is_normalized); - VCALL_LOCALMEM1R(Vector3, is_equal_approx); - VCALL_LOCALMEM0R(Vector3, inverse); - VCALL_LOCALMEM1R(Vector3, snapped); - VCALL_LOCALMEM2R(Vector3, rotated); - VCALL_LOCALMEM2R(Vector3, lerp); - VCALL_LOCALMEM2R(Vector3, slerp); - VCALL_LOCALMEM4R(Vector3, cubic_interpolate); - VCALL_LOCALMEM2R(Vector3, move_toward); - VCALL_LOCALMEM1R(Vector3, dot); - VCALL_LOCALMEM1R(Vector3, cross); - VCALL_LOCALMEM1R(Vector3, outer); - VCALL_LOCALMEM0R(Vector3, to_diagonal_matrix); - VCALL_LOCALMEM0R(Vector3, abs); - VCALL_LOCALMEM0R(Vector3, floor); - VCALL_LOCALMEM0R(Vector3, ceil); - VCALL_LOCALMEM0R(Vector3, round); - VCALL_LOCALMEM1R(Vector3, posmod); - VCALL_LOCALMEM1R(Vector3, posmodv); - VCALL_LOCALMEM1R(Vector3, project); - VCALL_LOCALMEM1R(Vector3, angle_to); - VCALL_LOCALMEM1R(Vector3, direction_to); - VCALL_LOCALMEM1R(Vector3, slide); - VCALL_LOCALMEM1R(Vector3, bounce); - VCALL_LOCALMEM1R(Vector3, reflect); - VCALL_LOCALMEM0R(Vector3, sign); - - VCALL_LOCALMEM0R(Vector3i, min_axis); - VCALL_LOCALMEM0R(Vector3i, max_axis); - VCALL_LOCALMEM0R(Vector3i, sign); - - VCALL_LOCALMEM0R(Plane, normalized); - VCALL_LOCALMEM0R(Plane, center); - VCALL_LOCALMEM1R(Plane, is_equal_approx); - VCALL_LOCALMEM1R(Plane, is_point_over); - VCALL_LOCALMEM1R(Plane, distance_to); - VCALL_LOCALMEM2R(Plane, has_point); - VCALL_LOCALMEM1R(Plane, project); - - //return vector3 if intersected, nil if not - static void _call_Plane_intersect_3(Variant &r_ret, Variant &p_self, const Variant **p_args) { - Vector3 result; - if (reinterpret_cast<Plane *>(p_self._data._mem)->intersect_3(*p_args[0], *p_args[1], &result)) { - r_ret = result; - } else { - r_ret = Variant(); - } - } - - static void _call_Plane_intersects_ray(Variant &r_ret, Variant &p_self, const Variant **p_args) { - Vector3 result; - if (reinterpret_cast<Plane *>(p_self._data._mem)->intersects_ray(*p_args[0], *p_args[1], &result)) { - r_ret = result; - } else { - r_ret = Variant(); - } - } - - static void _call_Plane_intersects_segment(Variant &r_ret, Variant &p_self, const Variant **p_args) { - Vector3 result; - if (reinterpret_cast<Plane *>(p_self._data._mem)->intersects_segment(*p_args[0], *p_args[1], &result)) { - r_ret = result; - } else { - r_ret = Variant(); - } - } - - VCALL_LOCALMEM0R(Quat, length); - VCALL_LOCALMEM0R(Quat, length_squared); - VCALL_LOCALMEM0R(Quat, normalized); - VCALL_LOCALMEM0R(Quat, is_normalized); - VCALL_LOCALMEM1R(Quat, is_equal_approx); - VCALL_LOCALMEM0R(Quat, inverse); - VCALL_LOCALMEM1R(Quat, dot); - VCALL_LOCALMEM1R(Quat, xform); - VCALL_LOCALMEM2R(Quat, slerp); - VCALL_LOCALMEM2R(Quat, slerpni); - VCALL_LOCALMEM4R(Quat, cubic_slerp); - VCALL_LOCALMEM0R(Quat, get_euler); - VCALL_LOCALMEM1(Quat, set_euler); - VCALL_LOCALMEM2(Quat, set_axis_angle); - - VCALL_LOCALMEM0R(Color, to_argb32); - VCALL_LOCALMEM0R(Color, to_abgr32); - VCALL_LOCALMEM0R(Color, to_rgba32); - VCALL_LOCALMEM0R(Color, to_argb64); - VCALL_LOCALMEM0R(Color, to_abgr64); - VCALL_LOCALMEM0R(Color, to_rgba64); - VCALL_LOCALMEM0R(Color, inverted); - VCALL_LOCALMEM0R(Color, contrasted); - VCALL_LOCALMEM2R(Color, lerp); - VCALL_LOCALMEM1R(Color, blend); - VCALL_LOCALMEM1R(Color, lightened); - VCALL_LOCALMEM1R(Color, darkened); - VCALL_LOCALMEM1R(Color, to_html); - VCALL_LOCALMEM4R(Color, from_hsv); - VCALL_LOCALMEM1R(Color, is_equal_approx); - - VCALL_LOCALMEM0R(RID, get_id); - - VCALL_LOCALMEM0R(NodePath, is_absolute); - VCALL_LOCALMEM0R(NodePath, get_name_count); - VCALL_LOCALMEM1R(NodePath, get_name); - VCALL_LOCALMEM0R(NodePath, get_subname_count); - VCALL_LOCALMEM1R(NodePath, get_subname); - VCALL_LOCALMEM0R(NodePath, get_concatenated_subnames); - VCALL_LOCALMEM0R(NodePath, get_as_property_path); - VCALL_LOCALMEM0R(NodePath, is_empty); - - VCALL_LOCALMEM0R(Dictionary, size); - VCALL_LOCALMEM0R(Dictionary, empty); - VCALL_LOCALMEM0(Dictionary, clear); - VCALL_LOCALMEM1R(Dictionary, has); - VCALL_LOCALMEM1R(Dictionary, has_all); - VCALL_LOCALMEM1R(Dictionary, erase); - VCALL_LOCALMEM0R(Dictionary, hash); - VCALL_LOCALMEM0R(Dictionary, keys); - VCALL_LOCALMEM0R(Dictionary, values); - VCALL_LOCALMEM1R(Dictionary, duplicate); - VCALL_LOCALMEM2R(Dictionary, get); - - VCALL_LOCALMEM0R(Callable, is_null); - VCALL_LOCALMEM0R(Callable, is_custom); - VCALL_LOCALMEM0(Callable, is_standard); - VCALL_LOCALMEM0(Callable, get_object); - VCALL_LOCALMEM0(Callable, get_object_id); - VCALL_LOCALMEM0(Callable, get_method); - VCALL_LOCALMEM0(Callable, hash); - VCALL_LOCALMEM1R(Callable, unbind); - - VCALL_LOCALMEM0R(Signal, is_null); - VCALL_LOCALMEM0R(Signal, get_object); - VCALL_LOCALMEM0R(Signal, get_object_id); - VCALL_LOCALMEM0R(Signal, get_name); - VCALL_LOCALMEM3R(Signal, connect); - VCALL_LOCALMEM1(Signal, disconnect); - VCALL_LOCALMEM1R(Signal, is_connected); - VCALL_LOCALMEM0R(Signal, get_connections); - - VCALL_LOCALMEM2(Array, set); - VCALL_LOCALMEM1R(Array, get); - VCALL_LOCALMEM0R(Array, size); - VCALL_LOCALMEM0R(Array, empty); - VCALL_LOCALMEM0(Array, clear); - VCALL_LOCALMEM0R(Array, hash); - VCALL_LOCALMEM1(Array, push_back); - VCALL_LOCALMEM1(Array, push_front); - VCALL_LOCALMEM0R(Array, pop_back); - VCALL_LOCALMEM0R(Array, pop_front); - VCALL_LOCALMEM1(Array, append); - VCALL_LOCALMEM1(Array, resize); - VCALL_LOCALMEM2(Array, insert); - VCALL_LOCALMEM1(Array, remove); - VCALL_LOCALMEM0R(Array, front); - VCALL_LOCALMEM0R(Array, back); - VCALL_LOCALMEM2R(Array, find); - VCALL_LOCALMEM2R(Array, rfind); - VCALL_LOCALMEM1R(Array, find_last); - VCALL_LOCALMEM1R(Array, count); - VCALL_LOCALMEM1R(Array, has); - VCALL_LOCALMEM1(Array, erase); - VCALL_LOCALMEM0(Array, sort); - VCALL_LOCALMEM2(Array, sort_custom); - VCALL_LOCALMEM0(Array, shuffle); - VCALL_LOCALMEM2R(Array, bsearch); - VCALL_LOCALMEM4R(Array, bsearch_custom); - VCALL_LOCALMEM1R(Array, duplicate); - VCALL_LOCALMEM4R(Array, slice); - VCALL_LOCALMEM0(Array, invert); - VCALL_LOCALMEM0R(Array, max); - VCALL_LOCALMEM0R(Array, min); - - static void _call_PackedByteArray_get_string_from_ascii(Variant &r_ret, Variant &p_self, const Variant **p_args) { - Variant::PackedArrayRef<uint8_t> *ba = reinterpret_cast<Variant::PackedArrayRef<uint8_t> *>(p_self._data.packed_array); - String s; - if (ba->array.size() > 0) { - const uint8_t *r = ba->array.ptr(); - CharString cs; - cs.resize(ba->array.size() + 1); - copymem(cs.ptrw(), r, ba->array.size()); - cs[ba->array.size()] = 0; - - s = cs.get_data(); - } - r_ret = s; - } - - static void _call_PackedByteArray_get_string_from_utf8(Variant &r_ret, Variant &p_self, const Variant **p_args) { - Variant::PackedArrayRef<uint8_t> *ba = reinterpret_cast<Variant::PackedArrayRef<uint8_t> *>(p_self._data.packed_array); - - String s; - if (ba->array.size() > 0) { - const uint8_t *r = ba->array.ptr(); - s.parse_utf8((const char *)r, ba->array.size()); - } - r_ret = s; - } - - static void _call_PackedByteArray_get_string_from_utf16(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); - String s; - if (ba->size() > 0) { - const uint8_t *r = ba->ptr(); - s.parse_utf16((const char16_t *)r, ba->size() / 2); - } - r_ret = s; - } - - static void _call_PackedByteArray_get_string_from_utf32(Variant &r_ret, Variant &p_self, const Variant **p_args) { - PackedByteArray *ba = reinterpret_cast<PackedByteArray *>(p_self._data._mem); - String s; - if (ba->size() > 0) { - const uint8_t *r = ba->ptr(); - s = String((const char32_t *)r, ba->size() / 4); - } - r_ret = s; - } - - static void _call_PackedByteArray_compress(Variant &r_ret, Variant &p_self, const Variant **p_args) { - Variant::PackedArrayRef<uint8_t> *ba = reinterpret_cast<Variant::PackedArrayRef<uint8_t> *>(p_self._data.packed_array); - PackedByteArray compressed; - - if (ba->array.size() > 0) { - Compression::Mode mode = (Compression::Mode)(int)(*p_args[0]); - compressed.resize(Compression::get_max_compressed_buffer_size(ba->array.size(), mode)); - int result = Compression::compress(compressed.ptrw(), ba->array.ptr(), ba->array.size(), mode); - - result = result >= 0 ? result : 0; - compressed.resize(result); - } - - r_ret = compressed; - } - - static void _call_PackedByteArray_decompress(Variant &r_ret, Variant &p_self, const Variant **p_args) { - Variant::PackedArrayRef<uint8_t> *ba = reinterpret_cast<Variant::PackedArrayRef<uint8_t> *>(p_self._data.packed_array); - PackedByteArray decompressed; - Compression::Mode mode = (Compression::Mode)(int)(*p_args[1]); - - int buffer_size = (int)(*p_args[0]); - - if (buffer_size <= 0) { - r_ret = decompressed; - ERR_FAIL_MSG("Decompression buffer size must be greater than zero."); - } - - decompressed.resize(buffer_size); - int result = Compression::decompress(decompressed.ptrw(), buffer_size, ba->array.ptr(), ba->array.size(), mode); - - result = result >= 0 ? result : 0; - decompressed.resize(result); - - r_ret = decompressed; - } - - static void _call_PackedByteArray_decompress_dynamic(Variant &r_ret, Variant &p_self, const Variant **p_args) { - Variant::PackedArrayRef<uint8_t> *ba = reinterpret_cast<Variant::PackedArrayRef<uint8_t> *>(p_self._data.packed_array); - PackedByteArray decompressed; - int max_output_size = (int)(*p_args[0]); - Compression::Mode mode = (Compression::Mode)(int)(*p_args[1]); - - int result = Compression::decompress_dynamic(&decompressed, max_output_size, ba->array.ptr(), ba->array.size(), mode); - - if (result == OK) { - r_ret = decompressed; - } else { - decompressed.clear(); - r_ret = decompressed; - ERR_FAIL_MSG("Decompression failed."); - } - } - - static void _call_PackedByteArray_hex_encode(Variant &r_ret, Variant &p_self, const Variant **p_args) { - Variant::PackedArrayRef<uint8_t> *ba = reinterpret_cast<Variant::PackedArrayRef<uint8_t> *>(p_self._data.packed_array); - if (ba->array.size() == 0) { - r_ret = String(); - return; - } - const uint8_t *r = ba->array.ptr(); - String s = String::hex_encode_buffer(&r[0], ba->array.size()); - r_ret = s; - } - -#define VCALL_PARRMEM0(m_type, m_elemtype, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(); } -#define VCALL_PARRMEM0R(m_type, m_elemtype, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(); } -#define VCALL_PARRMEM1(m_type, m_elemtype, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0]); } -#define VCALL_PARRMEM1R(m_type, m_elemtype, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0]); } -#define VCALL_PARRMEM2(m_type, m_elemtype, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1]); } -#define VCALL_PARRMEM2R(m_type, m_elemtype, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1]); } -#define VCALL_PARRMEM3(m_type, m_elemtype, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2]); } -#define VCALL_PARRMEM3R(m_type, m_elemtype, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2]); } -#define VCALL_PARRMEM4(m_type, m_elemtype, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); } -#define VCALL_PARRMEM4R(m_type, m_elemtype, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); } -#define VCALL_PARRMEM5(m_type, m_elemtype, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3], *p_args[4]); } -#define VCALL_PARRMEM5R(m_type, m_elemtype, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = Variant::PackedArrayRef<m_elemtype>::get_array_ptr(p_self._data.packed_array)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3], *p_args[4]); } - - VCALL_PARRMEM0R(PackedByteArray, uint8_t, size); - VCALL_PARRMEM0R(PackedByteArray, uint8_t, empty); - VCALL_PARRMEM2(PackedByteArray, uint8_t, set); - VCALL_PARRMEM1R(PackedByteArray, uint8_t, get); - VCALL_PARRMEM1(PackedByteArray, uint8_t, push_back); - VCALL_PARRMEM1(PackedByteArray, uint8_t, resize); - VCALL_PARRMEM2R(PackedByteArray, uint8_t, insert); - VCALL_PARRMEM1(PackedByteArray, uint8_t, remove); - VCALL_PARRMEM1(PackedByteArray, uint8_t, append); - VCALL_PARRMEM1(PackedByteArray, uint8_t, append_array); - VCALL_PARRMEM1R(PackedByteArray, uint8_t, has); - VCALL_PARRMEM0(PackedByteArray, uint8_t, sort); - VCALL_PARRMEM0(PackedByteArray, uint8_t, invert); - VCALL_PARRMEM2R(PackedByteArray, uint8_t, subarray); - - VCALL_PARRMEM0R(PackedInt32Array, int32_t, size); - VCALL_PARRMEM0R(PackedInt32Array, int32_t, empty); - VCALL_PARRMEM2(PackedInt32Array, int32_t, set); - VCALL_PARRMEM1R(PackedInt32Array, int32_t, get); - VCALL_PARRMEM1(PackedInt32Array, int32_t, push_back); - VCALL_PARRMEM1(PackedInt32Array, int32_t, resize); - VCALL_PARRMEM2R(PackedInt32Array, int32_t, insert); - VCALL_PARRMEM1(PackedInt32Array, int32_t, remove); - VCALL_PARRMEM1(PackedInt32Array, int32_t, append); - VCALL_PARRMEM1(PackedInt32Array, int32_t, append_array); - VCALL_PARRMEM1R(PackedInt32Array, int32_t, has); - VCALL_PARRMEM0(PackedInt32Array, int32_t, sort); - VCALL_PARRMEM0(PackedInt32Array, int32_t, invert); - - VCALL_PARRMEM0R(PackedInt64Array, int64_t, size); - VCALL_PARRMEM0R(PackedInt64Array, int64_t, empty); - VCALL_PARRMEM2(PackedInt64Array, int64_t, set); - VCALL_PARRMEM1R(PackedInt64Array, int64_t, get); - VCALL_PARRMEM1(PackedInt64Array, int64_t, push_back); - VCALL_PARRMEM1(PackedInt64Array, int64_t, resize); - VCALL_PARRMEM2R(PackedInt64Array, int64_t, insert); - VCALL_PARRMEM1(PackedInt64Array, int64_t, remove); - VCALL_PARRMEM1(PackedInt64Array, int64_t, append); - VCALL_PARRMEM1(PackedInt64Array, int64_t, append_array); - VCALL_PARRMEM1R(PackedInt64Array, int64_t, has); - VCALL_PARRMEM0(PackedInt64Array, int64_t, sort); - VCALL_PARRMEM0(PackedInt64Array, int64_t, invert); - - VCALL_PARRMEM0R(PackedFloat32Array, float, size); - VCALL_PARRMEM0R(PackedFloat32Array, float, empty); - VCALL_PARRMEM2(PackedFloat32Array, float, set); - VCALL_PARRMEM1R(PackedFloat32Array, float, get); - VCALL_PARRMEM1(PackedFloat32Array, float, push_back); - VCALL_PARRMEM1(PackedFloat32Array, float, resize); - VCALL_PARRMEM2R(PackedFloat32Array, float, insert); - VCALL_PARRMEM1(PackedFloat32Array, float, remove); - VCALL_PARRMEM1(PackedFloat32Array, float, append); - VCALL_PARRMEM1(PackedFloat32Array, float, append_array); - VCALL_PARRMEM1R(PackedFloat32Array, float, has); - VCALL_PARRMEM0(PackedFloat32Array, float, sort); - VCALL_PARRMEM0(PackedFloat32Array, float, invert); - - VCALL_PARRMEM0R(PackedFloat64Array, double, size); - VCALL_PARRMEM0R(PackedFloat64Array, double, empty); - VCALL_PARRMEM2(PackedFloat64Array, double, set); - VCALL_PARRMEM1R(PackedFloat64Array, double, get); - VCALL_PARRMEM1(PackedFloat64Array, double, push_back); - VCALL_PARRMEM1(PackedFloat64Array, double, resize); - VCALL_PARRMEM2R(PackedFloat64Array, double, insert); - VCALL_PARRMEM1(PackedFloat64Array, double, remove); - VCALL_PARRMEM1(PackedFloat64Array, double, append); - VCALL_PARRMEM1(PackedFloat64Array, double, append_array); - VCALL_PARRMEM1R(PackedFloat64Array, double, has); - VCALL_PARRMEM0(PackedFloat64Array, double, sort); - VCALL_PARRMEM0(PackedFloat64Array, double, invert); - - VCALL_PARRMEM0R(PackedStringArray, String, size); - VCALL_PARRMEM0R(PackedStringArray, String, empty); - VCALL_PARRMEM2(PackedStringArray, String, set); - VCALL_PARRMEM1R(PackedStringArray, String, get); - VCALL_PARRMEM1(PackedStringArray, String, push_back); - VCALL_PARRMEM1(PackedStringArray, String, resize); - VCALL_PARRMEM2R(PackedStringArray, String, insert); - VCALL_PARRMEM1(PackedStringArray, String, remove); - VCALL_PARRMEM1(PackedStringArray, String, append); - VCALL_PARRMEM1(PackedStringArray, String, append_array); - VCALL_PARRMEM1R(PackedStringArray, String, has); - VCALL_PARRMEM0(PackedStringArray, String, sort); - VCALL_PARRMEM0(PackedStringArray, String, invert); - - VCALL_PARRMEM0R(PackedVector2Array, Vector2, size); - VCALL_PARRMEM0R(PackedVector2Array, Vector2, empty); - VCALL_PARRMEM2(PackedVector2Array, Vector2, set); - VCALL_PARRMEM1R(PackedVector2Array, Vector2, get); - VCALL_PARRMEM1(PackedVector2Array, Vector2, push_back); - VCALL_PARRMEM1(PackedVector2Array, Vector2, resize); - VCALL_PARRMEM2R(PackedVector2Array, Vector2, insert); - VCALL_PARRMEM1(PackedVector2Array, Vector2, remove); - VCALL_PARRMEM1(PackedVector2Array, Vector2, append); - VCALL_PARRMEM1(PackedVector2Array, Vector2, append_array); - VCALL_PARRMEM1R(PackedVector2Array, Vector2, has); - VCALL_PARRMEM0(PackedVector2Array, Vector2, sort); - VCALL_PARRMEM0(PackedVector2Array, Vector2, invert); - - VCALL_PARRMEM0R(PackedVector3Array, Vector3, size); - VCALL_PARRMEM0R(PackedVector3Array, Vector3, empty); - VCALL_PARRMEM2(PackedVector3Array, Vector3, set); - VCALL_PARRMEM1R(PackedVector3Array, Vector3, get); - VCALL_PARRMEM1(PackedVector3Array, Vector3, push_back); - VCALL_PARRMEM1(PackedVector3Array, Vector3, resize); - VCALL_PARRMEM2R(PackedVector3Array, Vector3, insert); - VCALL_PARRMEM1(PackedVector3Array, Vector3, remove); - VCALL_PARRMEM1(PackedVector3Array, Vector3, append); - VCALL_PARRMEM1(PackedVector3Array, Vector3, append_array); - VCALL_PARRMEM1R(PackedVector3Array, Vector3, has); - VCALL_PARRMEM0(PackedVector3Array, Vector3, sort); - VCALL_PARRMEM0(PackedVector3Array, Vector3, invert); - - VCALL_PARRMEM0R(PackedColorArray, Color, size); - VCALL_PARRMEM0R(PackedColorArray, Color, empty); - VCALL_PARRMEM2(PackedColorArray, Color, set); - VCALL_PARRMEM1R(PackedColorArray, Color, get); - VCALL_PARRMEM1(PackedColorArray, Color, push_back); - VCALL_PARRMEM1(PackedColorArray, Color, resize); - VCALL_PARRMEM2R(PackedColorArray, Color, insert); - VCALL_PARRMEM1(PackedColorArray, Color, remove); - VCALL_PARRMEM1(PackedColorArray, Color, append); - VCALL_PARRMEM1(PackedColorArray, Color, append_array); - VCALL_PARRMEM1R(PackedColorArray, Color, has); - VCALL_PARRMEM0(PackedColorArray, Color, sort); - VCALL_PARRMEM0(PackedColorArray, Color, invert); - -#define VCALL_PTR0(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(); } -#define VCALL_PTR0R(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(); } -#define VCALL_PTR1(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(*p_args[0]); } -#define VCALL_PTR1R(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(*p_args[0]); } -#define VCALL_PTR2(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(*p_args[0], *p_args[1]); } -#define VCALL_PTR2R(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(*p_args[0], *p_args[1]); } -#define VCALL_PTR3(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(*p_args[0], *p_args[1], *p_args[2]); } -#define VCALL_PTR3R(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(*p_args[0], *p_args[1], *p_args[2]); } -#define VCALL_PTR4(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); } -#define VCALL_PTR4R(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); } -#define VCALL_PTR5(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3], *p_args[4]); } -#define VCALL_PTR5R(m_type, m_method) \ - static void _call_##m_type##_##m_method(Variant &r_ret, Variant &p_self, const Variant **p_args) { r_ret = reinterpret_cast<m_type *>(p_self._data._ptr)->m_method(*p_args[0], *p_args[1], *p_args[2], *p_args[3], *p_args[4]); } - - VCALL_PTR0R(AABB, abs); - VCALL_PTR0R(AABB, get_area); - VCALL_PTR0R(AABB, has_no_area); - VCALL_PTR0R(AABB, has_no_surface); - VCALL_PTR1R(AABB, has_point); - VCALL_PTR1R(AABB, is_equal_approx); - VCALL_PTR1R(AABB, intersects); - VCALL_PTR1R(AABB, encloses); - VCALL_PTR1R(AABB, intersects_plane); - VCALL_PTR2R(AABB, intersects_segment); - VCALL_PTR1R(AABB, intersection); - VCALL_PTR1R(AABB, merge); - VCALL_PTR1R(AABB, expand); - VCALL_PTR1R(AABB, grow); - VCALL_PTR1R(AABB, get_support); - VCALL_PTR0R(AABB, get_longest_axis); - VCALL_PTR0R(AABB, get_longest_axis_index); - VCALL_PTR0R(AABB, get_longest_axis_size); - VCALL_PTR0R(AABB, get_shortest_axis); - VCALL_PTR0R(AABB, get_shortest_axis_index); - VCALL_PTR0R(AABB, get_shortest_axis_size); - VCALL_PTR1R(AABB, get_endpoint); - - VCALL_PTR0R(Transform2D, inverse); - VCALL_PTR0R(Transform2D, affine_inverse); - VCALL_PTR0R(Transform2D, get_rotation); - VCALL_PTR0R(Transform2D, get_origin); - VCALL_PTR0R(Transform2D, get_scale); - VCALL_PTR0R(Transform2D, orthonormalized); - VCALL_PTR1R(Transform2D, rotated); - VCALL_PTR1R(Transform2D, scaled); - VCALL_PTR1R(Transform2D, translated); - VCALL_PTR2R(Transform2D, interpolate_with); - VCALL_PTR1R(Transform2D, is_equal_approx); - - static void _call_Transform2D_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - case Variant::VECTOR2: - r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Vector2()); - return; - case Variant::RECT2: - r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Rect2()); - return; - case Variant::PACKED_VECTOR2_ARRAY: - r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator PackedVector2Array()); - return; - default: - r_ret = Variant(); - ERR_PRINT("Invalid type in function 'xform' in base 'Transform2D'. Valid types are Vector2, Rect2, and PackedVector2Array."); - } - } - - static void _call_Transform2D_xform_inv(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - case Variant::VECTOR2: - r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector2()); - return; - case Variant::RECT2: - r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Rect2()); - return; - case Variant::PACKED_VECTOR2_ARRAY: - r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator PackedVector2Array()); - return; - default: - r_ret = Variant(); - ERR_PRINT("Invalid type in function 'xform_inv' in base 'Transform2D'. Valid types are Vector2, Rect2, and PackedVector2Array."); - } - } - - static void _call_Transform2D_basis_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - case Variant::VECTOR2: - r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->basis_xform(p_args[0]->operator Vector2()); - return; - default: - r_ret = Variant(); - ERR_PRINT("Invalid type in function 'basis_xform' in base 'Transform2D'. Only Vector2 is valid."); - } - } - - static void _call_Transform2D_basis_xform_inv(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - case Variant::VECTOR2: - r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->basis_xform_inv(p_args[0]->operator Vector2()); - return; - default: - r_ret = Variant(); - ERR_PRINT("Invalid type in function 'basis_xform_inv' in base 'Transform2D'. Only Vector2 is valid."); - } - } - - VCALL_PTR0R(Basis, inverse); - VCALL_PTR0R(Basis, transposed); - VCALL_PTR0R(Basis, determinant); - VCALL_PTR2R(Basis, rotated); - VCALL_PTR1R(Basis, scaled); - VCALL_PTR0R(Basis, get_scale); - VCALL_PTR0R(Basis, get_euler); - VCALL_PTR0R(Basis, get_euler_xyz); - VCALL_PTR1(Basis, set_euler_xyz); - VCALL_PTR0R(Basis, get_euler_xzy); - VCALL_PTR1(Basis, set_euler_xzy); - VCALL_PTR0R(Basis, get_euler_yzx); - VCALL_PTR1(Basis, set_euler_yzx); - VCALL_PTR0R(Basis, get_euler_yxz); - VCALL_PTR1(Basis, set_euler_yxz); - VCALL_PTR0R(Basis, get_euler_zxy); - VCALL_PTR1(Basis, set_euler_zxy); - VCALL_PTR0R(Basis, get_euler_zyx); - VCALL_PTR1(Basis, set_euler_zyx); - VCALL_PTR1R(Basis, tdotx); - VCALL_PTR1R(Basis, tdoty); - VCALL_PTR1R(Basis, tdotz); - VCALL_PTR1R(Basis, xform); - VCALL_PTR1R(Basis, xform_inv); - VCALL_PTR0R(Basis, get_orthogonal_index); - VCALL_PTR0R(Basis, orthonormalized); - VCALL_PTR2R(Basis, slerp); - VCALL_PTR1R(Basis, is_equal_approx); - VCALL_PTR0R(Basis, get_rotation_quat); - - VCALL_PTR0R(Transform, inverse); - VCALL_PTR0R(Transform, affine_inverse); - VCALL_PTR2R(Transform, rotated); - VCALL_PTR1R(Transform, scaled); - VCALL_PTR1R(Transform, translated); - VCALL_PTR0R(Transform, orthonormalized); - VCALL_PTR2R(Transform, looking_at); - VCALL_PTR2R(Transform, interpolate_with); - VCALL_PTR1R(Transform, is_equal_approx); - - static void _call_Transform_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - case Variant::VECTOR3: - r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Vector3()); - return; - case Variant::PLANE: - r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Plane()); - return; - case Variant::AABB: - r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::AABB()); - return; - case Variant::PACKED_VECTOR3_ARRAY: - r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::PackedVector3Array()); - return; - default: - r_ret = Variant(); - ERR_PRINT("Invalid type in function 'xform' in base 'Transform'. Valid types are Vector3, Plane, AABB, and PackedVector3Array."); - } - } - - static void _call_Transform_xform_inv(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - case Variant::VECTOR3: - r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector3()); - return; - case Variant::PLANE: - r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Plane()); - return; - case Variant::AABB: - r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::AABB()); - return; - case Variant::PACKED_VECTOR3_ARRAY: - r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::PackedVector3Array()); - return; - default: - r_ret = Variant(); - ERR_PRINT("Invalid type in function 'xform_inv' in base 'Transform'. Valid types are Vector3, Plane, AABB, and PackedVector3Array."); - } - } - - struct ConstructData { - int arg_count; - Vector<Variant::Type> arg_types; - Vector<String> arg_names; - VariantConstructFunc func; - }; - - struct ConstructFunc { - List<ConstructData> constructors; - }; - - static ConstructFunc *construct_funcs; - - static void Vector2_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Vector2(*p_args[0], *p_args[1]); - } - - static void Vector2i_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Vector2i(*p_args[0], *p_args[1]); - } - - static void Rect2_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Rect2(*p_args[0], *p_args[1]); - } - - static void Rect2_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Rect2(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); - } - - static void Rect2i_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Rect2i(*p_args[0], *p_args[1]); - } - - static void Rect2i_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Rect2i(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); - } - - static void Transform2D_init2(Variant &r_ret, const Variant **p_args) { - Transform2D m(*p_args[0], *p_args[1]); - r_ret = m; - } - - static void Transform2D_init3(Variant &r_ret, const Variant **p_args) { - Transform2D m; - m[0] = *p_args[0]; - m[1] = *p_args[1]; - m[2] = *p_args[2]; - r_ret = m; - } - - static void Vector3_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Vector3(*p_args[0], *p_args[1], *p_args[2]); - } - - static void Vector3i_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Vector3i(*p_args[0], *p_args[1], *p_args[2]); - } - - static void Plane_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Plane(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); - } - - static void Plane_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Plane(*p_args[0], *p_args[1], *p_args[2]); - } - - static void Plane_init3(Variant &r_ret, const Variant **p_args) { - r_ret = Plane(p_args[0]->operator Vector3(), p_args[1]->operator real_t()); - } - static void Plane_init4(Variant &r_ret, const Variant **p_args) { - r_ret = Plane(p_args[0]->operator Vector3(), p_args[1]->operator Vector3()); - } - - static void Quat_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Quat(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); - } - - static void Quat_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Quat(((Vector3)(*p_args[0])), ((real_t)(*p_args[1]))); - } - - static void Quat_init3(Variant &r_ret, const Variant **p_args) { - r_ret = Quat(((Vector3)(*p_args[0]))); - } - - static void Color_init1(Variant &r_ret, const Variant **p_args) { - r_ret = Color(*p_args[0], *p_args[1], *p_args[2], *p_args[3]); - } - - static void Color_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Color(*p_args[0], *p_args[1], *p_args[2]); - } - - static void Color_init3(Variant &r_ret, const Variant **p_args) { - r_ret = Color::html(*p_args[0]); - } - - static void Color_init4(Variant &r_ret, const Variant **p_args) { - r_ret = Color::hex(*p_args[0]); - } - - static void Color_init5(Variant &r_ret, const Variant **p_args) { - r_ret = Color(((Color)(*p_args[0])), *p_args[1]); - } - - static void AABB_init1(Variant &r_ret, const Variant **p_args) { - r_ret = ::AABB(*p_args[0], *p_args[1]); - } - - static void Basis_init1(Variant &r_ret, const Variant **p_args) { - Basis m; - m.set_axis(0, *p_args[0]); - m.set_axis(1, *p_args[1]); - m.set_axis(2, *p_args[2]); - r_ret = m; - } - - static void Basis_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Basis(p_args[0]->operator Vector3(), p_args[1]->operator real_t()); - } - - static void Transform_init1(Variant &r_ret, const Variant **p_args) { - Transform t; - t.basis.set_axis(0, *p_args[0]); - t.basis.set_axis(1, *p_args[1]); - t.basis.set_axis(2, *p_args[2]); - t.origin = *p_args[3]; - r_ret = t; - } - - static void Transform_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Transform(p_args[0]->operator Basis(), p_args[1]->operator Vector3()); - } - - static void Callable_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Callable(p_args[0]->operator ObjectID(), p_args[1]->operator String()); - } - - static void Signal_init2(Variant &r_ret, const Variant **p_args) { - r_ret = Signal(p_args[0]->operator ObjectID(), p_args[1]->operator String()); - } - - static void add_constructor(VariantConstructFunc p_func, const Variant::Type p_type, - const String &p_name1 = "", const Variant::Type p_type1 = Variant::NIL, - const String &p_name2 = "", const Variant::Type p_type2 = Variant::NIL, - const String &p_name3 = "", const Variant::Type p_type3 = Variant::NIL, - const String &p_name4 = "", const Variant::Type p_type4 = Variant::NIL) { - ConstructData cd; - cd.func = p_func; - cd.arg_count = 0; - - if (p_name1 == "") { - goto end; - } - cd.arg_count++; - cd.arg_names.push_back(p_name1); - cd.arg_types.push_back(p_type1); - - if (p_name2 == "") { - goto end; - } - cd.arg_count++; - cd.arg_names.push_back(p_name2); - cd.arg_types.push_back(p_type2); - - if (p_name3 == "") { - goto end; - } - cd.arg_count++; - cd.arg_names.push_back(p_name3); - cd.arg_types.push_back(p_type3); - - if (p_name4 == "") { - goto end; - } - cd.arg_count++; - cd.arg_names.push_back(p_name4); - cd.arg_types.push_back(p_type4); - - end: - - construct_funcs[p_type].constructors.push_back(cd); - } - - struct ConstantData { - Map<StringName, int> value; -#ifdef DEBUG_ENABLED - List<StringName> value_ordered; -#endif - Map<StringName, Variant> variant_value; -#ifdef DEBUG_ENABLED - List<StringName> variant_value_ordered; -#endif - }; - - static ConstantData *constant_data; - - static void add_constant(int p_type, StringName p_constant_name, int 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) { - 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); -#endif - } -}; - -_VariantCall::TypeFunc *_VariantCall::type_funcs = nullptr; -_VariantCall::ConstructFunc *_VariantCall::construct_funcs = nullptr; -_VariantCall::ConstantData *_VariantCall::constant_data = nullptr; - -Variant Variant::call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - Variant ret; - call_ptr(p_method, p_args, p_argcount, &ret, r_error); - return ret; -} - -void Variant::call_ptr(const StringName &p_method, const Variant **p_args, int p_argcount, Variant *r_ret, Callable::CallError &r_error) { - Variant ret; - - if (type == Variant::OBJECT) { - //call object - Object *obj = _get_obj().obj; - if (!obj) { - r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; - return; - } -#ifdef DEBUG_ENABLED - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - r_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; - return; - } - -#endif - ret = _get_obj().obj->call(p_method, p_args, p_argcount, r_error); - - //else if (type==Variant::METHOD) { - - } else { - r_error.error = Callable::CallError::CALL_OK; - - Map<StringName, _VariantCall::FuncData>::Element *E = _VariantCall::type_funcs[type].functions.find(p_method); - - if (E) { - _VariantCall::FuncData &funcdata = E->get(); - funcdata.call(ret, *this, p_args, p_argcount, r_error); - - } else { - //handle vararg functions manually - bool valid = false; - if (type == CALLABLE) { - if (p_method == CoreStringNames::get_singleton()->call) { - reinterpret_cast<const Callable *>(_data._mem)->call(p_args, p_argcount, ret, r_error); - valid = true; - } else if (p_method == CoreStringNames::get_singleton()->call_deferred) { - reinterpret_cast<const Callable *>(_data._mem)->call_deferred(p_args, p_argcount); - valid = true; - } else if (p_method == CoreStringNames::get_singleton()->bind) { - ret = reinterpret_cast<const Callable *>(_data._mem)->bind(p_args, p_argcount); - valid = true; - } - - } else if (type == SIGNAL) { - if (p_method == CoreStringNames::get_singleton()->emit) { - if (r_ret) { - *r_ret = Variant(); - } - reinterpret_cast<const Signal *>(_data._mem)->emit(p_args, p_argcount); - valid = true; - } - } - if (!valid) { - //ok fail because not found - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; - return; - } - } - } - - if (r_error.error == Callable::CallError::CALL_OK && r_ret) { - *r_ret = ret; - } -} - -#define VCALL(m_type, m_method) _VariantCall::_call_##m_type##_##m_method - -Variant Variant::construct(const Variant::Type p_type, const Variant **p_args, int p_argcount, Callable::CallError &r_error, bool p_strict) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; - ERR_FAIL_INDEX_V(p_type, VARIANT_MAX, Variant()); - - r_error.error = Callable::CallError::CALL_OK; - if (p_argcount == 0) { //generic construct - - switch (p_type) { - case NIL: - return Variant(); - - // atomic types - case BOOL: - return Variant(false); - case INT: - return 0; - case FLOAT: - return 0.0f; - case STRING: - return String(); - - // math types - case VECTOR2: - return Vector2(); - case VECTOR2I: - return Vector2i(); - case RECT2: - return Rect2(); - case RECT2I: - return Rect2i(); - case VECTOR3: - return Vector3(); - case VECTOR3I: - return Vector3i(); - case TRANSFORM2D: - return Transform2D(); - case PLANE: - return Plane(); - case QUAT: - return Quat(); - case AABB: - return ::AABB(); - case BASIS: - return Basis(); - case TRANSFORM: - return Transform(); - - // misc types - case COLOR: - return Color(); - case STRING_NAME: - return StringName(); - case NODE_PATH: - return NodePath(); - case _RID: - return RID(); - case OBJECT: - return (Object *)nullptr; - case CALLABLE: - return Callable(); - case SIGNAL: - return Signal(); - case DICTIONARY: - return Dictionary(); - case ARRAY: - return Array(); - case PACKED_BYTE_ARRAY: - return PackedByteArray(); - case PACKED_INT32_ARRAY: - return PackedInt32Array(); - case PACKED_INT64_ARRAY: - return PackedInt64Array(); - case PACKED_FLOAT32_ARRAY: - return PackedFloat32Array(); - case PACKED_FLOAT64_ARRAY: - return PackedFloat64Array(); - case PACKED_STRING_ARRAY: - return PackedStringArray(); - case PACKED_VECTOR2_ARRAY: - return PackedVector2Array(); - case PACKED_VECTOR3_ARRAY: - return PackedVector3Array(); - case PACKED_COLOR_ARRAY: - return PackedColorArray(); - default: - return Variant(); - } - - } else if (p_argcount == 1 && p_args[0]->type == p_type) { - return *p_args[0]; //copy construct - } else if (p_argcount == 1 && (!p_strict || Variant::can_convert(p_args[0]->type, p_type))) { - //near match construct - - switch (p_type) { - case NIL: { - return Variant(); - } break; - case BOOL: { - return Variant(bool(*p_args[0])); - } - case INT: { - return (int64_t(*p_args[0])); - } - case FLOAT: { - return double(*p_args[0]); - } - case STRING: { - return String(*p_args[0]); - } - case VECTOR2: { - return Vector2(*p_args[0]); - } - case VECTOR2I: { - return Vector2i(*p_args[0]); - } - case RECT2: - return (Rect2(*p_args[0])); - case RECT2I: - return (Rect2i(*p_args[0])); - case VECTOR3: - return (Vector3(*p_args[0])); - case VECTOR3I: - return (Vector3i(*p_args[0])); - case TRANSFORM2D: - return (Transform2D(p_args[0]->operator Transform2D())); - case PLANE: - return (Plane(*p_args[0])); - case QUAT: - return (p_args[0]->operator Quat()); - case AABB: - return (::AABB(*p_args[0])); - case BASIS: - return (Basis(p_args[0]->operator Basis())); - case TRANSFORM: - return (Transform(p_args[0]->operator Transform())); - - // misc types - case COLOR: - return p_args[0]->type == Variant::STRING ? Color::html(*p_args[0]) : Color::hex(*p_args[0]); - case STRING_NAME: - return (StringName(p_args[0]->operator StringName())); - case NODE_PATH: - return (NodePath(p_args[0]->operator NodePath())); - case _RID: - return (RID(*p_args[0])); - case OBJECT: - return ((Object *)(p_args[0]->operator Object *())); - case CALLABLE: - return ((Callable)(p_args[0]->operator Callable())); - case SIGNAL: - return ((Signal)(p_args[0]->operator Signal())); - case DICTIONARY: - return p_args[0]->operator Dictionary(); - case ARRAY: - return p_args[0]->operator Array(); - - // arrays - case PACKED_BYTE_ARRAY: - return (PackedByteArray(*p_args[0])); - case PACKED_INT32_ARRAY: - return (PackedInt32Array(*p_args[0])); - case PACKED_INT64_ARRAY: - return (PackedInt64Array(*p_args[0])); - case PACKED_FLOAT32_ARRAY: - return (PackedFloat32Array(*p_args[0])); - case PACKED_FLOAT64_ARRAY: - return (PackedFloat64Array(*p_args[0])); - case PACKED_STRING_ARRAY: - return (PackedStringArray(*p_args[0])); - case PACKED_VECTOR2_ARRAY: - return (PackedVector2Array(*p_args[0])); - case PACKED_VECTOR3_ARRAY: - return (PackedVector3Array(*p_args[0])); - case PACKED_COLOR_ARRAY: - return (PackedColorArray(*p_args[0])); - default: - return Variant(); - } - } else if (p_argcount >= 1) { - _VariantCall::ConstructFunc &c = _VariantCall::construct_funcs[p_type]; - - for (List<_VariantCall::ConstructData>::Element *E = c.constructors.front(); E; E = E->next()) { - const _VariantCall::ConstructData &cd = E->get(); - - if (cd.arg_count != p_argcount) { - continue; - } - - //validate parameters - for (int i = 0; i < cd.arg_count; i++) { - if (!Variant::can_convert(p_args[i]->type, cd.arg_types[i])) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; //no such constructor - r_error.argument = i; - r_error.expected = cd.arg_types[i]; - return Variant(); - } - } - - Variant v; - cd.func(v, p_args); - return v; - } - } - r_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; //no such constructor - return Variant(); -} - -bool Variant::has_method(const StringName &p_method) const { - if (type == OBJECT) { - Object *obj = get_validated_object(); - if (!obj) { - return false; - } - - return obj->has_method(p_method); - } - - const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[type]; - return tf.functions.has(p_method); -} - -Vector<Variant::Type> Variant::get_method_argument_types(Variant::Type p_type, const StringName &p_method) { - const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; - - const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); - if (!E) { - return Vector<Variant::Type>(); - } - - return E->get().arg_types; -} - -bool Variant::is_method_const(Variant::Type p_type, const StringName &p_method) { - const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; - - const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); - if (!E) { - return false; - } - - return E->get()._const; -} - -Vector<StringName> Variant::get_method_argument_names(Variant::Type p_type, const StringName &p_method) { - const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; - - const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); - if (!E) { - return Vector<StringName>(); - } - - return E->get().arg_names; -} - -Variant::Type Variant::get_method_return_type(Variant::Type p_type, const StringName &p_method, bool *r_has_return) { - const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; - - const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); - if (!E) { - return Variant::NIL; - } - - if (r_has_return) { - *r_has_return = E->get().returns; - } - - return E->get().return_type; -} - -Vector<Variant> Variant::get_method_default_arguments(Variant::Type p_type, const StringName &p_method) { - const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[p_type]; - - const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.find(p_method); - if (!E) { - return Vector<Variant>(); - } - - return E->get().default_args; -} - -void Variant::get_method_list(List<MethodInfo> *p_list) const { - const _VariantCall::TypeFunc &tf = _VariantCall::type_funcs[type]; - - for (const Map<StringName, _VariantCall::FuncData>::Element *E = tf.functions.front(); E; E = E->next()) { - const _VariantCall::FuncData &fd = E->get(); - - MethodInfo mi; - mi.name = E->key(); - - if (fd._const) { - mi.flags |= METHOD_FLAG_CONST; - } - - for (int i = 0; i < fd.arg_types.size(); i++) { - PropertyInfo pi; - pi.type = fd.arg_types[i]; -#ifdef DEBUG_ENABLED - pi.name = fd.arg_names[i]; -#endif - mi.arguments.push_back(pi); - } - - mi.default_arguments = fd.default_args; - PropertyInfo ret; -#ifdef DEBUG_ENABLED - ret.type = fd.return_type; - if (fd.returns) { - ret.name = "ret"; - if (fd.return_type == Variant::NIL) { - ret.usage = PROPERTY_USAGE_NIL_IS_VARIANT; - } - } - mi.return_val = ret; -#endif - - p_list->push_back(mi); - } - - if (type == CALLABLE) { - MethodInfo mi; - - mi.name = "bind"; - mi.flags |= METHOD_FLAG_VARARG; - p_list->push_back(mi); - - mi.name = "call"; - mi.return_val.usage = PROPERTY_USAGE_NIL_IS_VARIANT; - - p_list->push_back(mi); - - mi.name = "call_deferred"; - mi.return_val.usage = 0; - - p_list->push_back(mi); - } - - if (type == SIGNAL) { - MethodInfo mi; - mi.name = "emit"; - mi.flags |= METHOD_FLAG_VARARG; - - p_list->push_back(mi); - } -} - -void Variant::get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list) { - ERR_FAIL_INDEX(p_type, VARIANT_MAX); - - //custom constructors - for (const List<_VariantCall::ConstructData>::Element *E = _VariantCall::construct_funcs[p_type].constructors.front(); E; E = E->next()) { - const _VariantCall::ConstructData &cd = E->get(); - MethodInfo mi; - mi.name = Variant::get_type_name(p_type); - mi.return_val.type = p_type; - for (int i = 0; i < cd.arg_count; i++) { - PropertyInfo pi; - pi.name = cd.arg_names[i]; - pi.type = cd.arg_types[i]; - mi.arguments.push_back(pi); - } - p_list->push_back(mi); - } - //default constructors - for (int i = 0; i < VARIANT_MAX; i++) { - if (i == p_type) { - continue; - } - if (!Variant::can_convert(Variant::Type(i), p_type)) { - continue; - } - - MethodInfo mi; - mi.name = Variant::get_type_name(p_type); - PropertyInfo pi; - pi.name = "from"; - pi.type = Variant::Type(i); - mi.arguments.push_back(pi); - mi.return_val.type = p_type; - p_list->push_back(mi); - } -} - -void Variant::get_constants_for_type(Variant::Type p_type, List<StringName> *p_constants) { - ERR_FAIL_INDEX(p_type, Variant::VARIANT_MAX); - - _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type]; - -#ifdef DEBUG_ENABLED - for (List<StringName>::Element *E = cd.value_ordered.front(); E; E = E->next()) { - p_constants->push_back(E->get()); -#else - for (Map<StringName, int>::Element *E = cd.value.front(); E; E = E->next()) { - p_constants->push_back(E->key()); -#endif - } - -#ifdef DEBUG_ENABLED - for (List<StringName>::Element *E = cd.variant_value_ordered.front(); E; E = E->next()) { - p_constants->push_back(E->get()); -#else - for (Map<StringName, Variant>::Element *E = cd.variant_value.front(); E; E = E->next()) { - p_constants->push_back(E->key()); -#endif - } -} - -bool Variant::has_constant(Variant::Type p_type, const StringName &p_value) { - ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, false); - _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type]; - return cd.value.has(p_value) || cd.variant_value.has(p_value); -} - -Variant Variant::get_constant_value(Variant::Type p_type, const StringName &p_value, bool *r_valid) { - if (r_valid) { - *r_valid = false; - } - - ERR_FAIL_INDEX_V(p_type, Variant::VARIANT_MAX, 0); - _VariantCall::ConstantData &cd = _VariantCall::constant_data[p_type]; - - Map<StringName, int>::Element *E = cd.value.find(p_value); - if (!E) { - Map<StringName, Variant>::Element *F = cd.variant_value.find(p_value); - if (F) { - if (r_valid) { - *r_valid = true; - } - return F->get(); - } else { - return -1; - } - } - if (r_valid) { - *r_valid = true; - } - - return E->get(); -} - -void register_variant_methods() { - _VariantCall::type_funcs = memnew_arr(_VariantCall::TypeFunc, Variant::VARIANT_MAX); - - _VariantCall::construct_funcs = memnew_arr(_VariantCall::ConstructFunc, Variant::VARIANT_MAX); - _VariantCall::constant_data = memnew_arr(_VariantCall::ConstantData, Variant::VARIANT_MAX); - -#define ADDFUNC0R(m_vtype, m_ret, m_class, m_method, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg); -#define ADDFUNC1R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1))); -#define ADDFUNC2R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2))); -#define ADDFUNC3R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3))); -#define ADDFUNC4R(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4))); - -#define ADDFUNC0RNC(m_vtype, m_ret, m_class, m_method, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg); -#define ADDFUNC1RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1))); -#define ADDFUNC2RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2))); -#define ADDFUNC3RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3))); -#define ADDFUNC4RNC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, true, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4))); - -#define ADDFUNC0(m_vtype, m_ret, m_class, m_method, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg); -#define ADDFUNC1(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1))); -#define ADDFUNC2(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2))); -#define ADDFUNC3(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3))); -#define ADDFUNC4(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \ - _VariantCall::addfunc(true, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4))); - -#define ADDFUNC0NC(m_vtype, m_ret, m_class, m_method, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg); -#define ADDFUNC1NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1))); -#define ADDFUNC2NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2))); -#define ADDFUNC3NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3))); -#define ADDFUNC4NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_arg4, m_argname4, m_defarg) \ - _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, false, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)), _VariantCall::Arg(Variant::m_arg2, _scs_create(m_argname2)), _VariantCall::Arg(Variant::m_arg3, _scs_create(m_argname3)), _VariantCall::Arg(Variant::m_arg4, _scs_create(m_argname4))); - - /* STRING */ - ADDFUNC1R(STRING, INT, String, casecmp_to, STRING, "to", varray()); - ADDFUNC1R(STRING, INT, String, nocasecmp_to, STRING, "to", varray()); - ADDFUNC1R(STRING, INT, String, naturalnocasecmp_to, STRING, "to", varray()); - ADDFUNC0R(STRING, INT, String, length, varray()); - ADDFUNC2R(STRING, STRING, String, substr, INT, "from", INT, "len", varray(-1)); - - ADDFUNC2R(STRING, INT, String, find, STRING, "what", INT, "from", varray(0)); - - ADDFUNC3R(STRING, INT, String, count, STRING, "what", INT, "from", INT, "to", varray(0, 0)); - ADDFUNC3R(STRING, INT, String, countn, STRING, "what", INT, "from", INT, "to", varray(0, 0)); - - ADDFUNC2R(STRING, INT, String, findn, STRING, "what", INT, "from", varray(0)); - ADDFUNC2R(STRING, INT, String, rfind, STRING, "what", INT, "from", varray(-1)); - ADDFUNC2R(STRING, INT, String, rfindn, STRING, "what", INT, "from", varray(-1)); - ADDFUNC1R(STRING, BOOL, String, match, STRING, "expr", varray()); - ADDFUNC1R(STRING, BOOL, String, matchn, STRING, "expr", varray()); - ADDFUNC1R(STRING, BOOL, String, begins_with, STRING, "text", varray()); - ADDFUNC1R(STRING, BOOL, String, ends_with, STRING, "text", varray()); - ADDFUNC1R(STRING, BOOL, String, is_subsequence_of, STRING, "text", varray()); - ADDFUNC1R(STRING, BOOL, String, is_subsequence_ofi, STRING, "text", varray()); - ADDFUNC0R(STRING, PACKED_STRING_ARRAY, String, bigrams, varray()); - ADDFUNC1R(STRING, FLOAT, String, similarity, STRING, "text", varray()); - - ADDFUNC2R(STRING, STRING, String, format, NIL, "values", STRING, "placeholder", varray("{_}")); - ADDFUNC2R(STRING, STRING, String, replace, STRING, "what", STRING, "forwhat", varray()); - ADDFUNC2R(STRING, STRING, String, replacen, STRING, "what", STRING, "forwhat", varray()); - ADDFUNC1R(STRING, STRING, String, repeat, INT, "count", varray()); - ADDFUNC2R(STRING, STRING, String, insert, INT, "position", STRING, "what", varray()); - ADDFUNC0R(STRING, STRING, String, capitalize, varray()); - ADDFUNC3R(STRING, PACKED_STRING_ARRAY, String, split, STRING, "delimiter", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); - ADDFUNC3R(STRING, PACKED_STRING_ARRAY, String, rsplit, STRING, "delimiter", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); - ADDFUNC2R(STRING, PACKED_FLOAT32_ARRAY, String, split_floats, STRING, "delimiter", BOOL, "allow_empty", varray(true)); - ADDFUNC1R(STRING, STRING, String, join, PACKED_STRING_ARRAY, "parts", varray()); - - ADDFUNC0R(STRING, STRING, String, to_upper, varray()); - ADDFUNC0R(STRING, STRING, String, to_lower, varray()); - - ADDFUNC1R(STRING, STRING, String, left, INT, "position", varray()); - ADDFUNC1R(STRING, STRING, String, right, INT, "position", varray()); - ADDFUNC2R(STRING, STRING, String, strip_edges, BOOL, "left", BOOL, "right", varray(true, true)); - ADDFUNC0R(STRING, STRING, String, strip_escapes, varray()); - ADDFUNC1R(STRING, STRING, String, lstrip, STRING, "chars", varray()); - ADDFUNC1R(STRING, STRING, String, rstrip, STRING, "chars", varray()); - ADDFUNC0R(STRING, STRING, String, get_extension, varray()); - ADDFUNC0R(STRING, STRING, String, get_basename, varray()); - ADDFUNC1R(STRING, STRING, String, plus_file, STRING, "file", varray()); - ADDFUNC1R(STRING, INT, String, ord_at, INT, "at", varray()); - ADDFUNC0R(STRING, STRING, String, dedent, varray()); - ADDFUNC2(STRING, NIL, String, erase, INT, "position", INT, "chars", varray()); - ADDFUNC0R(STRING, INT, String, hash, varray()); - ADDFUNC0R(STRING, STRING, String, md5_text, varray()); - ADDFUNC0R(STRING, STRING, String, sha1_text, varray()); - ADDFUNC0R(STRING, STRING, String, sha256_text, varray()); - ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, md5_buffer, varray()); - ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, sha1_buffer, varray()); - ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, sha256_buffer, varray()); - ADDFUNC0R(STRING, BOOL, String, empty, varray()); - ADDFUNC1R(STRING, STRING, String, humanize_size, INT, "size", varray()); - ADDFUNC0R(STRING, BOOL, String, is_abs_path, varray()); - ADDFUNC0R(STRING, BOOL, String, is_rel_path, varray()); - ADDFUNC0R(STRING, STRING, String, get_base_dir, varray()); - ADDFUNC0R(STRING, STRING, String, get_file, varray()); - ADDFUNC0R(STRING, STRING, String, xml_escape, varray()); - ADDFUNC0R(STRING, STRING, String, xml_unescape, varray()); - ADDFUNC0R(STRING, STRING, String, http_escape, varray()); - ADDFUNC0R(STRING, STRING, String, http_unescape, varray()); - ADDFUNC0R(STRING, STRING, String, c_escape, varray()); - ADDFUNC0R(STRING, STRING, String, c_unescape, varray()); - ADDFUNC0R(STRING, STRING, String, json_escape, varray()); - ADDFUNC0R(STRING, STRING, String, percent_encode, varray()); - ADDFUNC0R(STRING, STRING, String, percent_decode, varray()); - ADDFUNC0R(STRING, BOOL, String, is_valid_identifier, varray()); - ADDFUNC0R(STRING, BOOL, String, is_valid_integer, varray()); - ADDFUNC0R(STRING, BOOL, String, is_valid_float, varray()); - ADDFUNC1R(STRING, BOOL, String, is_valid_hex_number, BOOL, "with_prefix", varray(false)); - ADDFUNC0R(STRING, BOOL, String, is_valid_html_color, varray()); - ADDFUNC0R(STRING, BOOL, String, is_valid_ip_address, varray()); - ADDFUNC0R(STRING, BOOL, String, is_valid_filename, varray()); - ADDFUNC0R(STRING, INT, String, to_int, varray()); - ADDFUNC0R(STRING, FLOAT, String, to_float, varray()); - ADDFUNC0R(STRING, INT, String, hex_to_int, varray()); - ADDFUNC2R(STRING, STRING, String, lpad, INT, "min_length", STRING, "character", varray(" ")); - ADDFUNC2R(STRING, STRING, String, rpad, INT, "min_length", STRING, "character", varray(" ")); - ADDFUNC1R(STRING, STRING, String, pad_decimals, INT, "digits", varray()); - ADDFUNC1R(STRING, STRING, String, pad_zeros, INT, "digits", varray()); - ADDFUNC1R(STRING, STRING, String, trim_prefix, STRING, "prefix", varray()); - ADDFUNC1R(STRING, STRING, String, trim_suffix, STRING, "suffix", varray()); - - ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_ascii, varray()); - ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_utf8, varray()); - ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_utf16, varray()); - ADDFUNC0R(STRING, PACKED_BYTE_ARRAY, String, to_utf32, varray()); - - ADDFUNC0R(VECTOR2, FLOAT, Vector2, angle, varray()); - ADDFUNC1R(VECTOR2, FLOAT, Vector2, angle_to, VECTOR2, "to", varray()); - ADDFUNC1R(VECTOR2, FLOAT, Vector2, angle_to_point, VECTOR2, "to", varray()); - ADDFUNC1R(VECTOR2, VECTOR2, Vector2, direction_to, VECTOR2, "b", varray()); - ADDFUNC1R(VECTOR2, FLOAT, Vector2, distance_to, VECTOR2, "to", varray()); - ADDFUNC1R(VECTOR2, FLOAT, Vector2, distance_squared_to, VECTOR2, "to", varray()); - ADDFUNC0R(VECTOR2, FLOAT, Vector2, length, varray()); - ADDFUNC0R(VECTOR2, FLOAT, Vector2, length_squared, varray()); - ADDFUNC0R(VECTOR2, VECTOR2, Vector2, normalized, varray()); - ADDFUNC0R(VECTOR2, BOOL, Vector2, is_normalized, varray()); - ADDFUNC1R(VECTOR2, BOOL, Vector2, is_equal_approx, VECTOR2, "v", varray()); - ADDFUNC1R(VECTOR2, VECTOR2, Vector2, posmod, FLOAT, "mod", varray()); - ADDFUNC1R(VECTOR2, VECTOR2, Vector2, posmodv, VECTOR2, "modv", varray()); - ADDFUNC1R(VECTOR2, VECTOR2, Vector2, project, VECTOR2, "b", varray()); - ADDFUNC2R(VECTOR2, VECTOR2, Vector2, lerp, VECTOR2, "b", FLOAT, "t", varray()); - ADDFUNC2R(VECTOR2, VECTOR2, Vector2, slerp, VECTOR2, "b", FLOAT, "t", varray()); - ADDFUNC4R(VECTOR2, VECTOR2, Vector2, cubic_interpolate, VECTOR2, "b", VECTOR2, "pre_a", VECTOR2, "post_b", FLOAT, "t", varray()); - ADDFUNC2R(VECTOR2, VECTOR2, Vector2, move_toward, VECTOR2, "to", FLOAT, "delta", varray()); - ADDFUNC1R(VECTOR2, VECTOR2, Vector2, rotated, FLOAT, "phi", varray()); - ADDFUNC0R(VECTOR2, VECTOR2, Vector2, tangent, varray()); - ADDFUNC0R(VECTOR2, VECTOR2, Vector2, floor, varray()); - ADDFUNC0R(VECTOR2, VECTOR2, Vector2, ceil, varray()); - ADDFUNC0R(VECTOR2, VECTOR2, Vector2, round, varray()); - ADDFUNC1R(VECTOR2, VECTOR2, Vector2, snapped, VECTOR2, "by", varray()); - ADDFUNC0R(VECTOR2, FLOAT, Vector2, aspect, varray()); - ADDFUNC1R(VECTOR2, FLOAT, Vector2, dot, VECTOR2, "with", varray()); - ADDFUNC1R(VECTOR2, VECTOR2, Vector2, slide, VECTOR2, "n", varray()); - ADDFUNC1R(VECTOR2, VECTOR2, Vector2, bounce, VECTOR2, "n", varray()); - ADDFUNC1R(VECTOR2, VECTOR2, Vector2, reflect, VECTOR2, "n", varray()); - ADDFUNC1R(VECTOR2, FLOAT, Vector2, cross, VECTOR2, "with", varray()); - ADDFUNC0R(VECTOR2, VECTOR2, Vector2, abs, varray()); - ADDFUNC1R(VECTOR2, VECTOR2, Vector2, clamped, FLOAT, "length", varray()); - ADDFUNC0R(VECTOR2, VECTOR2, Vector2, sign, varray()); - - ADDFUNC0R(VECTOR2I, FLOAT, Vector2i, aspect, varray()); - ADDFUNC0R(VECTOR2I, VECTOR2I, Vector2i, sign, varray()); - ADDFUNC0R(VECTOR2I, VECTOR2I, Vector2i, abs, varray()); - - ADDFUNC0R(RECT2, FLOAT, Rect2, get_area, varray()); - ADDFUNC0R(RECT2, BOOL, Rect2, has_no_area, varray()); - ADDFUNC1R(RECT2, BOOL, Rect2, has_point, VECTOR2, "point", varray()); - ADDFUNC1R(RECT2, BOOL, Rect2, is_equal_approx, RECT2, "rect", varray()); - ADDFUNC2R(RECT2, BOOL, Rect2, intersects, RECT2, "b", BOOL, "include_borders", varray(false)); - ADDFUNC1R(RECT2, BOOL, Rect2, encloses, RECT2, "b", varray()); - ADDFUNC1R(RECT2, RECT2, Rect2, clip, RECT2, "b", varray()); - ADDFUNC1R(RECT2, RECT2, Rect2, merge, RECT2, "b", varray()); - ADDFUNC1R(RECT2, RECT2, Rect2, expand, VECTOR2, "to", varray()); - ADDFUNC1R(RECT2, RECT2, Rect2, grow, FLOAT, "by", varray()); - ADDFUNC2R(RECT2, RECT2, Rect2, grow_margin, INT, "margin", FLOAT, "by", varray()); - ADDFUNC4R(RECT2, RECT2, Rect2, grow_individual, FLOAT, "left", FLOAT, "top", FLOAT, "right", FLOAT, " bottom", varray()); - ADDFUNC0R(RECT2, RECT2, Rect2, abs, varray()); - - ADDFUNC0R(RECT2I, INT, Rect2i, get_area, varray()); - ADDFUNC0R(RECT2I, BOOL, Rect2i, has_no_area, varray()); - ADDFUNC1R(RECT2I, BOOL, Rect2i, has_point, VECTOR2I, "point", varray()); - ADDFUNC1R(RECT2I, BOOL, Rect2i, intersects, RECT2I, "b", varray()); - ADDFUNC1R(RECT2I, BOOL, Rect2i, encloses, RECT2I, "b", varray()); - ADDFUNC1R(RECT2I, RECT2I, Rect2i, clip, RECT2I, "b", varray()); - ADDFUNC1R(RECT2I, RECT2I, Rect2i, merge, RECT2I, "b", varray()); - ADDFUNC1R(RECT2I, RECT2I, Rect2i, expand, VECTOR2I, "to", varray()); - ADDFUNC1R(RECT2I, RECT2I, Rect2i, grow, INT, "by", varray()); - ADDFUNC2R(RECT2I, RECT2I, Rect2i, grow_margin, INT, "margin", INT, "by", varray()); - ADDFUNC4R(RECT2I, RECT2I, Rect2i, grow_individual, INT, "left", INT, "top", INT, "right", INT, " bottom", varray()); - ADDFUNC0R(RECT2I, RECT2I, Rect2i, abs, varray()); - - ADDFUNC0R(VECTOR3, INT, Vector3, min_axis, varray()); - ADDFUNC0R(VECTOR3, INT, Vector3, max_axis, varray()); - ADDFUNC1R(VECTOR3, FLOAT, Vector3, angle_to, VECTOR3, "to", varray()); - ADDFUNC1R(VECTOR3, VECTOR3, Vector3, direction_to, VECTOR3, "b", varray()); - ADDFUNC1R(VECTOR3, FLOAT, Vector3, distance_to, VECTOR3, "b", varray()); - ADDFUNC1R(VECTOR3, FLOAT, Vector3, distance_squared_to, VECTOR3, "b", varray()); - ADDFUNC0R(VECTOR3, FLOAT, Vector3, length, varray()); - ADDFUNC0R(VECTOR3, FLOAT, Vector3, length_squared, varray()); - ADDFUNC0R(VECTOR3, VECTOR3, Vector3, normalized, varray()); - ADDFUNC0R(VECTOR3, BOOL, Vector3, is_normalized, varray()); - ADDFUNC1R(VECTOR3, BOOL, Vector3, is_equal_approx, VECTOR3, "v", varray()); - ADDFUNC0R(VECTOR3, VECTOR3, Vector3, inverse, varray()); - ADDFUNC1R(VECTOR3, VECTOR3, Vector3, snapped, VECTOR3, "by", varray()); - ADDFUNC2R(VECTOR3, VECTOR3, Vector3, rotated, VECTOR3, "axis", FLOAT, "phi", varray()); - ADDFUNC2R(VECTOR3, VECTOR3, Vector3, lerp, VECTOR3, "b", FLOAT, "t", varray()); - ADDFUNC2R(VECTOR3, VECTOR3, Vector3, slerp, VECTOR3, "b", FLOAT, "t", varray()); - ADDFUNC4R(VECTOR3, VECTOR3, Vector3, cubic_interpolate, VECTOR3, "b", VECTOR3, "pre_a", VECTOR3, "post_b", FLOAT, "t", varray()); - ADDFUNC2R(VECTOR3, VECTOR3, Vector3, move_toward, VECTOR3, "to", FLOAT, "delta", varray()); - ADDFUNC1R(VECTOR3, FLOAT, Vector3, dot, VECTOR3, "b", varray()); - ADDFUNC1R(VECTOR3, VECTOR3, Vector3, cross, VECTOR3, "b", varray()); - ADDFUNC1R(VECTOR3, BASIS, Vector3, outer, VECTOR3, "b", varray()); - ADDFUNC0R(VECTOR3, BASIS, Vector3, to_diagonal_matrix, varray()); - ADDFUNC0R(VECTOR3, VECTOR3, Vector3, abs, varray()); - ADDFUNC0R(VECTOR3, VECTOR3, Vector3, floor, varray()); - ADDFUNC0R(VECTOR3, VECTOR3, Vector3, ceil, varray()); - ADDFUNC0R(VECTOR3, VECTOR3, Vector3, round, varray()); - ADDFUNC1R(VECTOR3, VECTOR3, Vector3, posmod, FLOAT, "mod", varray()); - ADDFUNC1R(VECTOR3, VECTOR3, Vector3, posmodv, VECTOR3, "modv", varray()); - ADDFUNC1R(VECTOR3, VECTOR3, Vector3, project, VECTOR3, "b", varray()); - ADDFUNC1R(VECTOR3, VECTOR3, Vector3, slide, VECTOR3, "n", varray()); - ADDFUNC1R(VECTOR3, VECTOR3, Vector3, bounce, VECTOR3, "n", varray()); - ADDFUNC1R(VECTOR3, VECTOR3, Vector3, reflect, VECTOR3, "n", varray()); - ADDFUNC0R(VECTOR3, VECTOR3, Vector3, sign, varray()); - - ADDFUNC0R(VECTOR3I, INT, Vector3i, min_axis, varray()); - ADDFUNC0R(VECTOR3I, INT, Vector3i, max_axis, varray()); - ADDFUNC0R(VECTOR3I, VECTOR3I, Vector3i, sign, varray()); - - ADDFUNC0R(PLANE, PLANE, Plane, normalized, varray()); - ADDFUNC0R(PLANE, VECTOR3, Plane, center, varray()); - ADDFUNC1R(PLANE, BOOL, Plane, is_equal_approx, PLANE, "plane", varray()); - ADDFUNC1R(PLANE, BOOL, Plane, is_point_over, VECTOR3, "point", varray()); - ADDFUNC1R(PLANE, FLOAT, Plane, distance_to, VECTOR3, "point", varray()); - ADDFUNC2R(PLANE, BOOL, Plane, has_point, VECTOR3, "point", FLOAT, "epsilon", varray(CMP_EPSILON)); - ADDFUNC1R(PLANE, VECTOR3, Plane, project, VECTOR3, "point", varray()); - ADDFUNC2R(PLANE, VECTOR3, Plane, intersect_3, PLANE, "b", PLANE, "c", varray()); - ADDFUNC2R(PLANE, VECTOR3, Plane, intersects_ray, VECTOR3, "from", VECTOR3, "dir", varray()); - ADDFUNC2R(PLANE, VECTOR3, Plane, intersects_segment, VECTOR3, "begin", VECTOR3, "end", varray()); - - ADDFUNC0R(QUAT, FLOAT, Quat, length, varray()); - ADDFUNC0R(QUAT, FLOAT, Quat, length_squared, varray()); - ADDFUNC0R(QUAT, QUAT, Quat, normalized, varray()); - ADDFUNC0R(QUAT, BOOL, Quat, is_normalized, varray()); - ADDFUNC1R(QUAT, BOOL, Quat, is_equal_approx, QUAT, "quat", varray()); - ADDFUNC0R(QUAT, QUAT, Quat, inverse, varray()); - ADDFUNC1R(QUAT, FLOAT, Quat, dot, QUAT, "b", varray()); - ADDFUNC1R(QUAT, VECTOR3, Quat, xform, VECTOR3, "v", varray()); - ADDFUNC2R(QUAT, QUAT, Quat, slerp, QUAT, "b", FLOAT, "t", varray()); - ADDFUNC2R(QUAT, QUAT, Quat, slerpni, QUAT, "b", FLOAT, "t", varray()); - ADDFUNC4R(QUAT, QUAT, Quat, cubic_slerp, QUAT, "b", QUAT, "pre_a", QUAT, "post_b", FLOAT, "t", varray()); - ADDFUNC0R(QUAT, VECTOR3, Quat, get_euler, varray()); - ADDFUNC1(QUAT, NIL, Quat, set_euler, VECTOR3, "euler", varray()); - ADDFUNC2(QUAT, NIL, Quat, set_axis_angle, VECTOR3, "axis", FLOAT, "angle", varray()); - - ADDFUNC0R(COLOR, INT, Color, to_argb32, varray()); - ADDFUNC0R(COLOR, INT, Color, to_abgr32, varray()); - ADDFUNC0R(COLOR, INT, Color, to_rgba32, varray()); - ADDFUNC0R(COLOR, INT, Color, to_argb64, varray()); - ADDFUNC0R(COLOR, INT, Color, to_abgr64, varray()); - ADDFUNC0R(COLOR, INT, Color, to_rgba64, varray()); - ADDFUNC0R(COLOR, COLOR, Color, inverted, varray()); - ADDFUNC0R(COLOR, COLOR, Color, contrasted, varray()); - ADDFUNC2R(COLOR, COLOR, Color, lerp, COLOR, "b", FLOAT, "t", varray()); - ADDFUNC1R(COLOR, COLOR, Color, blend, COLOR, "over", varray()); - ADDFUNC1R(COLOR, COLOR, Color, lightened, FLOAT, "amount", varray()); - ADDFUNC1R(COLOR, COLOR, Color, darkened, FLOAT, "amount", varray()); - ADDFUNC1R(COLOR, STRING, Color, to_html, BOOL, "with_alpha", varray(true)); - ADDFUNC4R(COLOR, COLOR, Color, from_hsv, FLOAT, "h", FLOAT, "s", FLOAT, "v", FLOAT, "a", varray(1.0)); - ADDFUNC1R(COLOR, BOOL, Color, is_equal_approx, COLOR, "color", varray()); - - ADDFUNC0R(_RID, INT, RID, get_id, varray()); - - ADDFUNC0R(NODE_PATH, BOOL, NodePath, is_absolute, varray()); - ADDFUNC0R(NODE_PATH, INT, NodePath, get_name_count, varray()); - ADDFUNC1R(NODE_PATH, STRING, NodePath, get_name, INT, "idx", varray()); - ADDFUNC0R(NODE_PATH, INT, NodePath, get_subname_count, varray()); - ADDFUNC1R(NODE_PATH, STRING, NodePath, get_subname, INT, "idx", varray()); - ADDFUNC0R(NODE_PATH, STRING, NodePath, get_concatenated_subnames, varray()); - ADDFUNC0R(NODE_PATH, NODE_PATH, NodePath, get_as_property_path, varray()); - ADDFUNC0R(NODE_PATH, BOOL, NodePath, is_empty, varray()); - - ADDFUNC0R(DICTIONARY, INT, Dictionary, size, varray()); - ADDFUNC0R(DICTIONARY, BOOL, Dictionary, empty, varray()); - ADDFUNC0NC(DICTIONARY, NIL, Dictionary, clear, varray()); - ADDFUNC1R(DICTIONARY, BOOL, Dictionary, has, NIL, "key", varray()); - ADDFUNC1R(DICTIONARY, BOOL, Dictionary, has_all, ARRAY, "keys", varray()); - ADDFUNC1RNC(DICTIONARY, BOOL, Dictionary, erase, NIL, "key", varray()); - ADDFUNC0R(DICTIONARY, INT, Dictionary, hash, varray()); - ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, keys, varray()); - ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, values, varray()); - ADDFUNC1R(DICTIONARY, DICTIONARY, Dictionary, duplicate, BOOL, "deep", varray(false)); - ADDFUNC2R(DICTIONARY, NIL, Dictionary, get, NIL, "key", NIL, "default", varray(Variant())); - - ADDFUNC0R(CALLABLE, BOOL, Callable, is_null, varray()); - ADDFUNC0R(CALLABLE, BOOL, Callable, is_custom, varray()); - ADDFUNC0R(CALLABLE, BOOL, Callable, is_standard, varray()); - ADDFUNC0R(CALLABLE, OBJECT, Callable, get_object, varray()); - ADDFUNC0R(CALLABLE, INT, Callable, get_object_id, varray()); - ADDFUNC0R(CALLABLE, STRING_NAME, Callable, get_method, varray()); - ADDFUNC0R(CALLABLE, INT, Callable, hash, varray()); - ADDFUNC1R(CALLABLE, CALLABLE, Callable, unbind, INT, "argcount", varray()); - - ADDFUNC0R(SIGNAL, BOOL, Signal, is_null, varray()); - ADDFUNC0R(SIGNAL, OBJECT, Signal, get_object, varray()); - ADDFUNC0R(SIGNAL, INT, Signal, get_object_id, varray()); - ADDFUNC0R(SIGNAL, STRING_NAME, Signal, get_name, varray()); - - ADDFUNC3R(SIGNAL, INT, Signal, connect, CALLABLE, "callable", ARRAY, "binds", INT, "flags", varray(Array(), 0)); - - ADDFUNC1R(SIGNAL, NIL, Signal, disconnect, CALLABLE, "callable", varray()); - ADDFUNC1R(SIGNAL, BOOL, Signal, is_connected, CALLABLE, "callable", varray()); - ADDFUNC0R(SIGNAL, ARRAY, Signal, get_connections, varray()); - - ADDFUNC0R(ARRAY, INT, Array, size, varray()); - ADDFUNC0R(ARRAY, BOOL, Array, empty, varray()); - ADDFUNC0NC(ARRAY, NIL, Array, clear, varray()); - ADDFUNC0R(ARRAY, INT, Array, hash, varray()); - ADDFUNC1NC(ARRAY, NIL, Array, push_back, NIL, "value", varray()); - ADDFUNC1NC(ARRAY, NIL, Array, push_front, NIL, "value", varray()); - ADDFUNC1NC(ARRAY, NIL, Array, append, NIL, "value", varray()); - ADDFUNC1NC(ARRAY, NIL, Array, resize, INT, "size", varray()); - ADDFUNC2NC(ARRAY, NIL, Array, insert, INT, "position", NIL, "value", varray()); - ADDFUNC1NC(ARRAY, NIL, Array, remove, INT, "position", varray()); - ADDFUNC1NC(ARRAY, NIL, Array, erase, NIL, "value", varray()); - ADDFUNC0R(ARRAY, NIL, Array, front, varray()); - ADDFUNC0R(ARRAY, NIL, Array, back, varray()); - ADDFUNC2R(ARRAY, INT, Array, find, NIL, "what", INT, "from", varray(0)); - ADDFUNC2R(ARRAY, INT, Array, rfind, NIL, "what", INT, "from", varray(-1)); - ADDFUNC1R(ARRAY, INT, Array, find_last, NIL, "value", varray()); - ADDFUNC1R(ARRAY, INT, Array, count, NIL, "value", varray()); - ADDFUNC1R(ARRAY, BOOL, Array, has, NIL, "value", varray()); - ADDFUNC0RNC(ARRAY, NIL, Array, pop_back, varray()); - ADDFUNC0RNC(ARRAY, NIL, Array, pop_front, varray()); - ADDFUNC0NC(ARRAY, NIL, Array, sort, varray()); - ADDFUNC2NC(ARRAY, NIL, Array, sort_custom, OBJECT, "obj", STRING, "func", varray()); - ADDFUNC0NC(ARRAY, NIL, Array, shuffle, varray()); - ADDFUNC2R(ARRAY, INT, Array, bsearch, NIL, "value", BOOL, "before", varray(true)); - ADDFUNC4R(ARRAY, INT, Array, bsearch_custom, NIL, "value", OBJECT, "obj", STRING, "func", BOOL, "before", varray(true)); - ADDFUNC0NC(ARRAY, NIL, Array, invert, varray()); - ADDFUNC1R(ARRAY, ARRAY, Array, duplicate, BOOL, "deep", varray(false)); - ADDFUNC4R(ARRAY, ARRAY, Array, slice, INT, "begin", INT, "end", INT, "step", BOOL, "deep", varray(1, false)); - ADDFUNC0R(ARRAY, NIL, Array, max, varray()); - ADDFUNC0R(ARRAY, NIL, Array, min, varray()); - - ADDFUNC0R(PACKED_BYTE_ARRAY, INT, PackedByteArray, size, varray()); - ADDFUNC0R(PACKED_BYTE_ARRAY, BOOL, PackedByteArray, empty, varray()); - ADDFUNC2(PACKED_BYTE_ARRAY, NIL, PackedByteArray, set, INT, "idx", INT, "byte", varray()); - ADDFUNC1(PACKED_BYTE_ARRAY, NIL, PackedByteArray, push_back, INT, "byte", varray()); - ADDFUNC1(PACKED_BYTE_ARRAY, NIL, PackedByteArray, append, INT, "byte", varray()); - ADDFUNC1(PACKED_BYTE_ARRAY, NIL, PackedByteArray, append_array, PACKED_BYTE_ARRAY, "array", varray()); - ADDFUNC1(PACKED_BYTE_ARRAY, NIL, PackedByteArray, remove, INT, "idx", varray()); - ADDFUNC2R(PACKED_BYTE_ARRAY, INT, PackedByteArray, insert, INT, "idx", INT, "byte", varray()); - ADDFUNC1(PACKED_BYTE_ARRAY, NIL, PackedByteArray, resize, INT, "idx", varray()); - ADDFUNC1R(PACKED_BYTE_ARRAY, BOOL, PackedByteArray, has, INT, "value", varray()); - ADDFUNC0(PACKED_BYTE_ARRAY, NIL, PackedByteArray, sort, varray()); - ADDFUNC0(PACKED_BYTE_ARRAY, NIL, PackedByteArray, invert, varray()); - ADDFUNC2R(PACKED_BYTE_ARRAY, PACKED_BYTE_ARRAY, PackedByteArray, subarray, INT, "from", INT, "to", varray()); - - ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_ascii, varray()); - ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_utf8, varray()); - ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_utf16, varray()); - ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, get_string_from_utf32, varray()); - ADDFUNC0R(PACKED_BYTE_ARRAY, STRING, PackedByteArray, hex_encode, varray()); - ADDFUNC1R(PACKED_BYTE_ARRAY, PACKED_BYTE_ARRAY, PackedByteArray, compress, INT, "compression_mode", varray(0)); - ADDFUNC2R(PACKED_BYTE_ARRAY, PACKED_BYTE_ARRAY, PackedByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0)); - ADDFUNC2R(PACKED_BYTE_ARRAY, PACKED_BYTE_ARRAY, PackedByteArray, decompress_dynamic, INT, "max_output_size", INT, "compression_mode", varray(0)); - - ADDFUNC0R(PACKED_INT32_ARRAY, INT, PackedInt32Array, size, varray()); - ADDFUNC0R(PACKED_INT32_ARRAY, BOOL, PackedInt32Array, empty, varray()); - ADDFUNC2(PACKED_INT32_ARRAY, NIL, PackedInt32Array, set, INT, "idx", INT, "integer", varray()); - ADDFUNC1(PACKED_INT32_ARRAY, NIL, PackedInt32Array, push_back, INT, "integer", varray()); - ADDFUNC1(PACKED_INT32_ARRAY, NIL, PackedInt32Array, append, INT, "integer", varray()); - ADDFUNC1(PACKED_INT32_ARRAY, NIL, PackedInt32Array, append_array, PACKED_INT32_ARRAY, "array", varray()); - ADDFUNC1(PACKED_INT32_ARRAY, NIL, PackedInt32Array, remove, INT, "idx", varray()); - ADDFUNC2R(PACKED_INT32_ARRAY, INT, PackedInt32Array, insert, INT, "idx", INT, "integer", varray()); - ADDFUNC1(PACKED_INT32_ARRAY, NIL, PackedInt32Array, resize, INT, "idx", varray()); - ADDFUNC1R(PACKED_INT32_ARRAY, BOOL, PackedInt32Array, has, INT, "value", varray()); - ADDFUNC0(PACKED_INT32_ARRAY, NIL, PackedInt32Array, sort, varray()); - ADDFUNC0(PACKED_INT32_ARRAY, NIL, PackedInt32Array, invert, varray()); - - ADDFUNC0R(PACKED_INT64_ARRAY, INT, PackedInt64Array, size, varray()); - ADDFUNC0R(PACKED_INT64_ARRAY, BOOL, PackedInt64Array, empty, varray()); - ADDFUNC2(PACKED_INT64_ARRAY, NIL, PackedInt64Array, set, INT, "idx", INT, "integer", varray()); - ADDFUNC1(PACKED_INT64_ARRAY, NIL, PackedInt64Array, push_back, INT, "integer", varray()); - ADDFUNC1(PACKED_INT64_ARRAY, NIL, PackedInt64Array, append, INT, "integer", varray()); - ADDFUNC1(PACKED_INT64_ARRAY, NIL, PackedInt64Array, append_array, PACKED_INT64_ARRAY, "array", varray()); - ADDFUNC1(PACKED_INT64_ARRAY, NIL, PackedInt64Array, remove, INT, "idx", varray()); - ADDFUNC2R(PACKED_INT64_ARRAY, INT, PackedInt64Array, insert, INT, "idx", INT, "integer", varray()); - ADDFUNC1(PACKED_INT64_ARRAY, NIL, PackedInt64Array, resize, INT, "idx", varray()); - ADDFUNC1R(PACKED_INT64_ARRAY, BOOL, PackedInt64Array, has, INT, "value", varray()); - ADDFUNC0(PACKED_INT64_ARRAY, NIL, PackedInt64Array, sort, varray()); - ADDFUNC0(PACKED_INT64_ARRAY, NIL, PackedInt64Array, invert, varray()); - - ADDFUNC0R(PACKED_FLOAT32_ARRAY, INT, PackedFloat32Array, size, varray()); - ADDFUNC0R(PACKED_FLOAT32_ARRAY, BOOL, PackedFloat32Array, empty, varray()); - ADDFUNC2(PACKED_FLOAT32_ARRAY, NIL, PackedFloat32Array, set, INT, "idx", FLOAT, "value", varray()); - ADDFUNC1(PACKED_FLOAT32_ARRAY, NIL, PackedFloat32Array, push_back, FLOAT, "value", varray()); - ADDFUNC1(PACKED_FLOAT32_ARRAY, NIL, PackedFloat32Array, append, FLOAT, "value", varray()); - ADDFUNC1(PACKED_FLOAT32_ARRAY, NIL, PackedFloat32Array, append_array, PACKED_FLOAT32_ARRAY, "array", varray()); - ADDFUNC1(PACKED_FLOAT32_ARRAY, NIL, PackedFloat32Array, remove, INT, "idx", varray()); - ADDFUNC2R(PACKED_FLOAT32_ARRAY, INT, PackedFloat32Array, insert, INT, "idx", FLOAT, "value", varray()); - ADDFUNC1(PACKED_FLOAT32_ARRAY, NIL, PackedFloat32Array, resize, INT, "idx", varray()); - ADDFUNC1R(PACKED_FLOAT32_ARRAY, BOOL, PackedFloat32Array, has, FLOAT, "value", varray()); - ADDFUNC0(PACKED_FLOAT32_ARRAY, NIL, PackedFloat32Array, sort, varray()); - ADDFUNC0(PACKED_FLOAT32_ARRAY, NIL, PackedFloat32Array, invert, varray()); - - ADDFUNC0R(PACKED_FLOAT64_ARRAY, INT, PackedFloat64Array, size, varray()); - ADDFUNC0R(PACKED_FLOAT64_ARRAY, BOOL, PackedFloat64Array, empty, varray()); - ADDFUNC2(PACKED_FLOAT64_ARRAY, NIL, PackedFloat64Array, set, INT, "idx", FLOAT, "value", varray()); - ADDFUNC1(PACKED_FLOAT64_ARRAY, NIL, PackedFloat64Array, push_back, FLOAT, "value", varray()); - ADDFUNC1(PACKED_FLOAT64_ARRAY, NIL, PackedFloat64Array, append, FLOAT, "value", varray()); - ADDFUNC1(PACKED_FLOAT64_ARRAY, NIL, PackedFloat64Array, append_array, PACKED_FLOAT64_ARRAY, "array", varray()); - ADDFUNC1(PACKED_FLOAT64_ARRAY, NIL, PackedFloat64Array, remove, INT, "idx", varray()); - ADDFUNC2R(PACKED_FLOAT64_ARRAY, INT, PackedFloat64Array, insert, INT, "idx", FLOAT, "value", varray()); - ADDFUNC1(PACKED_FLOAT64_ARRAY, NIL, PackedFloat64Array, resize, INT, "idx", varray()); - ADDFUNC1R(PACKED_FLOAT64_ARRAY, BOOL, PackedFloat64Array, has, FLOAT, "value", varray()); - ADDFUNC0(PACKED_FLOAT64_ARRAY, NIL, PackedFloat64Array, sort, varray()); - ADDFUNC0(PACKED_FLOAT64_ARRAY, NIL, PackedFloat64Array, invert, varray()); - - ADDFUNC0R(PACKED_STRING_ARRAY, INT, PackedStringArray, size, varray()); - ADDFUNC0R(PACKED_STRING_ARRAY, BOOL, PackedStringArray, empty, varray()); - ADDFUNC2(PACKED_STRING_ARRAY, NIL, PackedStringArray, set, INT, "idx", STRING, "string", varray()); - ADDFUNC1(PACKED_STRING_ARRAY, NIL, PackedStringArray, push_back, STRING, "string", varray()); - ADDFUNC1(PACKED_STRING_ARRAY, NIL, PackedStringArray, append, STRING, "string", varray()); - ADDFUNC1(PACKED_STRING_ARRAY, NIL, PackedStringArray, append_array, PACKED_STRING_ARRAY, "array", varray()); - ADDFUNC1(PACKED_STRING_ARRAY, NIL, PackedStringArray, remove, INT, "idx", varray()); - ADDFUNC2R(PACKED_STRING_ARRAY, INT, PackedStringArray, insert, INT, "idx", STRING, "string", varray()); - ADDFUNC1(PACKED_STRING_ARRAY, NIL, PackedStringArray, resize, INT, "idx", varray()); - ADDFUNC1R(PACKED_STRING_ARRAY, BOOL, PackedStringArray, has, STRING, "value", varray()); - ADDFUNC0(PACKED_STRING_ARRAY, NIL, PackedStringArray, sort, varray()); - ADDFUNC0(PACKED_STRING_ARRAY, NIL, PackedStringArray, invert, varray()); - - ADDFUNC0R(PACKED_VECTOR2_ARRAY, INT, PackedVector2Array, size, varray()); - ADDFUNC0R(PACKED_VECTOR2_ARRAY, BOOL, PackedVector2Array, empty, varray()); - ADDFUNC2(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, set, INT, "idx", VECTOR2, "vector2", varray()); - ADDFUNC1(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, push_back, VECTOR2, "vector2", varray()); - ADDFUNC1(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, append, VECTOR2, "vector2", varray()); - ADDFUNC1(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, append_array, PACKED_VECTOR2_ARRAY, "array", varray()); - ADDFUNC1(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, remove, INT, "idx", varray()); - ADDFUNC2R(PACKED_VECTOR2_ARRAY, INT, PackedVector2Array, insert, INT, "idx", VECTOR2, "vector2", varray()); - ADDFUNC1(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, resize, INT, "idx", varray()); - ADDFUNC1R(PACKED_VECTOR2_ARRAY, BOOL, PackedVector2Array, has, VECTOR2, "value", varray()); - ADDFUNC0(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, sort, varray()); - ADDFUNC0(PACKED_VECTOR2_ARRAY, NIL, PackedVector2Array, invert, varray()); - - ADDFUNC0R(PACKED_VECTOR3_ARRAY, INT, PackedVector3Array, size, varray()); - ADDFUNC0R(PACKED_VECTOR3_ARRAY, BOOL, PackedVector3Array, empty, varray()); - ADDFUNC2(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, set, INT, "idx", VECTOR3, "vector3", varray()); - ADDFUNC1(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, push_back, VECTOR3, "vector3", varray()); - ADDFUNC1(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, append, VECTOR3, "vector3", varray()); - ADDFUNC1(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, append_array, PACKED_VECTOR3_ARRAY, "array", varray()); - ADDFUNC1(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, remove, INT, "idx", varray()); - ADDFUNC2R(PACKED_VECTOR3_ARRAY, INT, PackedVector3Array, insert, INT, "idx", VECTOR3, "vector3", varray()); - ADDFUNC1(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, resize, INT, "idx", varray()); - ADDFUNC1R(PACKED_VECTOR3_ARRAY, BOOL, PackedVector3Array, has, VECTOR3, "value", varray()); - ADDFUNC0(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, sort, varray()); - ADDFUNC0(PACKED_VECTOR3_ARRAY, NIL, PackedVector3Array, invert, varray()); - - ADDFUNC0R(PACKED_COLOR_ARRAY, INT, PackedColorArray, size, varray()); - ADDFUNC0R(PACKED_COLOR_ARRAY, BOOL, PackedColorArray, empty, varray()); - ADDFUNC2(PACKED_COLOR_ARRAY, NIL, PackedColorArray, set, INT, "idx", COLOR, "color", varray()); - ADDFUNC1(PACKED_COLOR_ARRAY, NIL, PackedColorArray, push_back, COLOR, "color", varray()); - ADDFUNC1(PACKED_COLOR_ARRAY, NIL, PackedColorArray, append, COLOR, "color", varray()); - ADDFUNC1(PACKED_COLOR_ARRAY, NIL, PackedColorArray, append_array, PACKED_COLOR_ARRAY, "array", varray()); - ADDFUNC1(PACKED_COLOR_ARRAY, NIL, PackedColorArray, remove, INT, "idx", varray()); - ADDFUNC2R(PACKED_COLOR_ARRAY, INT, PackedColorArray, insert, INT, "idx", COLOR, "color", varray()); - ADDFUNC1(PACKED_COLOR_ARRAY, NIL, PackedColorArray, resize, INT, "idx", varray()); - ADDFUNC1R(PACKED_COLOR_ARRAY, BOOL, PackedColorArray, has, COLOR, "value", varray()); - ADDFUNC0(PACKED_COLOR_ARRAY, NIL, PackedColorArray, sort, varray()); - ADDFUNC0(PACKED_COLOR_ARRAY, NIL, PackedColorArray, invert, varray()); - - //pointerbased - - ADDFUNC0R(AABB, AABB, AABB, abs, varray()); - ADDFUNC0R(AABB, FLOAT, AABB, get_area, varray()); - ADDFUNC0R(AABB, BOOL, AABB, has_no_area, varray()); - ADDFUNC0R(AABB, BOOL, AABB, has_no_surface, varray()); - ADDFUNC1R(AABB, BOOL, AABB, has_point, VECTOR3, "point", varray()); - ADDFUNC1R(AABB, BOOL, AABB, is_equal_approx, AABB, "aabb", varray()); - ADDFUNC1R(AABB, BOOL, AABB, intersects, AABB, "with", varray()); - ADDFUNC1R(AABB, BOOL, AABB, encloses, AABB, "with", varray()); - ADDFUNC1R(AABB, BOOL, AABB, intersects_plane, PLANE, "plane", varray()); - ADDFUNC2R(AABB, BOOL, AABB, intersects_segment, VECTOR3, "from", VECTOR3, "to", varray()); - ADDFUNC1R(AABB, AABB, AABB, intersection, AABB, "with", varray()); - ADDFUNC1R(AABB, AABB, AABB, merge, AABB, "with", varray()); - ADDFUNC1R(AABB, AABB, AABB, expand, VECTOR3, "to_point", varray()); - ADDFUNC1R(AABB, AABB, AABB, grow, FLOAT, "by", varray()); - ADDFUNC1R(AABB, VECTOR3, AABB, get_support, VECTOR3, "dir", varray()); - ADDFUNC0R(AABB, VECTOR3, AABB, get_longest_axis, varray()); - ADDFUNC0R(AABB, INT, AABB, get_longest_axis_index, varray()); - ADDFUNC0R(AABB, FLOAT, AABB, get_longest_axis_size, varray()); - ADDFUNC0R(AABB, VECTOR3, AABB, get_shortest_axis, varray()); - ADDFUNC0R(AABB, INT, AABB, get_shortest_axis_index, varray()); - ADDFUNC0R(AABB, FLOAT, AABB, get_shortest_axis_size, varray()); - ADDFUNC1R(AABB, VECTOR3, AABB, get_endpoint, INT, "idx", varray()); - - ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, inverse, varray()); - ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, affine_inverse, varray()); - ADDFUNC0R(TRANSFORM2D, FLOAT, Transform2D, get_rotation, varray()); - ADDFUNC0R(TRANSFORM2D, VECTOR2, Transform2D, get_origin, varray()); - ADDFUNC0R(TRANSFORM2D, VECTOR2, Transform2D, get_scale, varray()); - ADDFUNC0R(TRANSFORM2D, TRANSFORM2D, Transform2D, orthonormalized, varray()); - ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, rotated, FLOAT, "phi", varray()); - ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, scaled, VECTOR2, "scale", varray()); - ADDFUNC1R(TRANSFORM2D, TRANSFORM2D, Transform2D, translated, VECTOR2, "offset", varray()); - ADDFUNC1R(TRANSFORM2D, NIL, Transform2D, xform, NIL, "v", varray()); - ADDFUNC1R(TRANSFORM2D, NIL, Transform2D, xform_inv, NIL, "v", varray()); - ADDFUNC1R(TRANSFORM2D, VECTOR2, Transform2D, basis_xform, VECTOR2, "v", varray()); - ADDFUNC1R(TRANSFORM2D, VECTOR2, Transform2D, basis_xform_inv, VECTOR2, "v", varray()); - ADDFUNC2R(TRANSFORM2D, TRANSFORM2D, Transform2D, interpolate_with, TRANSFORM2D, "transform", FLOAT, "weight", varray()); - ADDFUNC1R(TRANSFORM2D, BOOL, Transform2D, is_equal_approx, TRANSFORM2D, "transform", varray()); - - ADDFUNC0R(BASIS, BASIS, Basis, inverse, varray()); - ADDFUNC0R(BASIS, BASIS, Basis, transposed, varray()); - ADDFUNC0R(BASIS, BASIS, Basis, orthonormalized, varray()); - ADDFUNC0R(BASIS, FLOAT, Basis, determinant, varray()); - ADDFUNC2R(BASIS, BASIS, Basis, rotated, VECTOR3, "axis", FLOAT, "phi", varray()); - ADDFUNC1R(BASIS, BASIS, Basis, scaled, VECTOR3, "scale", varray()); - ADDFUNC0R(BASIS, VECTOR3, Basis, get_scale, varray()); - ADDFUNC0R(BASIS, VECTOR3, Basis, get_euler, varray()); - ADDFUNC1R(BASIS, FLOAT, Basis, tdotx, VECTOR3, "with", varray()); - ADDFUNC1R(BASIS, FLOAT, Basis, tdoty, VECTOR3, "with", varray()); - ADDFUNC1R(BASIS, FLOAT, Basis, tdotz, VECTOR3, "with", varray()); - ADDFUNC1R(BASIS, VECTOR3, Basis, xform, VECTOR3, "v", varray()); - ADDFUNC1R(BASIS, VECTOR3, Basis, xform_inv, VECTOR3, "v", varray()); - ADDFUNC0R(BASIS, INT, Basis, get_orthogonal_index, varray()); - ADDFUNC2R(BASIS, BASIS, Basis, slerp, BASIS, "b", FLOAT, "t", varray()); - ADDFUNC1R(BASIS, BOOL, Basis, is_equal_approx, BASIS, "b", varray()); - ADDFUNC0R(BASIS, QUAT, Basis, get_rotation_quat, varray()); - - ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, inverse, varray()); - ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, affine_inverse, varray()); - ADDFUNC0R(TRANSFORM, TRANSFORM, Transform, orthonormalized, varray()); - ADDFUNC2R(TRANSFORM, TRANSFORM, Transform, rotated, VECTOR3, "axis", FLOAT, "phi", varray()); - ADDFUNC1R(TRANSFORM, TRANSFORM, Transform, scaled, VECTOR3, "scale", varray()); - ADDFUNC1R(TRANSFORM, TRANSFORM, Transform, translated, VECTOR3, "offset", varray()); - ADDFUNC2R(TRANSFORM, TRANSFORM, Transform, looking_at, VECTOR3, "target", VECTOR3, "up", varray()); - ADDFUNC2R(TRANSFORM, TRANSFORM, Transform, interpolate_with, TRANSFORM, "transform", FLOAT, "weight", varray()); - ADDFUNC1R(TRANSFORM, BOOL, Transform, is_equal_approx, TRANSFORM, "transform", varray()); - ADDFUNC1R(TRANSFORM, NIL, Transform, xform, NIL, "v", varray()); - ADDFUNC1R(TRANSFORM, NIL, Transform, xform_inv, NIL, "v", varray()); - - /* REGISTER CONSTRUCTORS */ - - _VariantCall::add_constructor(_VariantCall::Vector2_init1, Variant::VECTOR2, "x", Variant::FLOAT, "y", Variant::FLOAT); - _VariantCall::add_constructor(_VariantCall::Vector2i_init1, Variant::VECTOR2I, "x", Variant::INT, "y", Variant::INT); - - _VariantCall::add_constructor(_VariantCall::Rect2_init1, Variant::RECT2, "position", Variant::VECTOR2, "size", Variant::VECTOR2); - _VariantCall::add_constructor(_VariantCall::Rect2_init2, Variant::RECT2, "x", Variant::FLOAT, "y", Variant::FLOAT, "width", Variant::FLOAT, "height", Variant::FLOAT); - - _VariantCall::add_constructor(_VariantCall::Rect2i_init1, Variant::RECT2I, "position", Variant::VECTOR2, "size", Variant::VECTOR2); - _VariantCall::add_constructor(_VariantCall::Rect2i_init2, Variant::RECT2I, "x", Variant::INT, "y", Variant::INT, "width", Variant::INT, "height", Variant::INT); - - _VariantCall::add_constructor(_VariantCall::Transform2D_init2, Variant::TRANSFORM2D, "rotation", Variant::FLOAT, "position", Variant::VECTOR2); - _VariantCall::add_constructor(_VariantCall::Transform2D_init3, Variant::TRANSFORM2D, "x_axis", Variant::VECTOR2, "y_axis", Variant::VECTOR2, "origin", Variant::VECTOR2); - - _VariantCall::add_constructor(_VariantCall::Vector3_init1, Variant::VECTOR3, "x", Variant::FLOAT, "y", Variant::FLOAT, "z", Variant::FLOAT); - _VariantCall::add_constructor(_VariantCall::Vector3i_init1, Variant::VECTOR3I, "x", Variant::INT, "y", Variant::INT, "z", Variant::INT); - - _VariantCall::add_constructor(_VariantCall::Plane_init1, Variant::PLANE, "a", Variant::FLOAT, "b", Variant::FLOAT, "c", Variant::FLOAT, "d", Variant::FLOAT); - _VariantCall::add_constructor(_VariantCall::Plane_init2, Variant::PLANE, "v1", Variant::VECTOR3, "v2", Variant::VECTOR3, "v3", Variant::VECTOR3); - _VariantCall::add_constructor(_VariantCall::Plane_init3, Variant::PLANE, "normal", Variant::VECTOR3, "d", Variant::FLOAT); - - _VariantCall::add_constructor(_VariantCall::Quat_init1, Variant::QUAT, "x", Variant::FLOAT, "y", Variant::FLOAT, "z", Variant::FLOAT, "w", Variant::FLOAT); - _VariantCall::add_constructor(_VariantCall::Quat_init2, Variant::QUAT, "axis", Variant::VECTOR3, "angle", Variant::FLOAT); - _VariantCall::add_constructor(_VariantCall::Quat_init3, Variant::QUAT, "euler", Variant::VECTOR3); - - _VariantCall::add_constructor(_VariantCall::Color_init1, Variant::COLOR, "r", Variant::FLOAT, "g", Variant::FLOAT, "b", Variant::FLOAT, "a", Variant::FLOAT); - _VariantCall::add_constructor(_VariantCall::Color_init2, Variant::COLOR, "r", Variant::FLOAT, "g", Variant::FLOAT, "b", Variant::FLOAT); - // init3 and init4 are the constructors for HTML hex strings and integers respectively which don't need binding here, so we skip to init5. - _VariantCall::add_constructor(_VariantCall::Color_init5, Variant::COLOR, "c", Variant::COLOR, "a", Variant::FLOAT); - - _VariantCall::add_constructor(_VariantCall::AABB_init1, Variant::AABB, "position", Variant::VECTOR3, "size", Variant::VECTOR3); - - _VariantCall::add_constructor(_VariantCall::Basis_init1, Variant::BASIS, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3); - _VariantCall::add_constructor(_VariantCall::Basis_init2, Variant::BASIS, "axis", Variant::VECTOR3, "phi", Variant::FLOAT); - - _VariantCall::add_constructor(_VariantCall::Transform_init1, Variant::TRANSFORM, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3, "origin", Variant::VECTOR3); - _VariantCall::add_constructor(_VariantCall::Transform_init2, Variant::TRANSFORM, "basis", Variant::BASIS, "origin", Variant::VECTOR3); - - _VariantCall::add_constructor(_VariantCall::Callable_init2, Variant::CALLABLE, "object", Variant::OBJECT, "method_name", Variant::STRING_NAME); - _VariantCall::add_constructor(_VariantCall::Signal_init2, Variant::SIGNAL, "object", Variant::OBJECT, "signal_name", Variant::STRING_NAME); - - /* REGISTER CONSTANTS */ - - _populate_named_colors(); - for (Map<String, Color>::Element *color = _named_colors.front(); color; color = color->next()) { - _VariantCall::add_variant_constant(Variant::COLOR, color->key(), color->value()); - } - - _VariantCall::add_constant(Variant::VECTOR3, "AXIS_X", Vector3::AXIS_X); - _VariantCall::add_constant(Variant::VECTOR3, "AXIS_Y", Vector3::AXIS_Y); - _VariantCall::add_constant(Variant::VECTOR3, "AXIS_Z", Vector3::AXIS_Z); - - _VariantCall::add_variant_constant(Variant::VECTOR3, "ZERO", Vector3(0, 0, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR3, "ONE", Vector3(1, 1, 1)); - _VariantCall::add_variant_constant(Variant::VECTOR3, "INF", Vector3(Math_INF, Math_INF, Math_INF)); - _VariantCall::add_variant_constant(Variant::VECTOR3, "LEFT", Vector3(-1, 0, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR3, "RIGHT", Vector3(1, 0, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR3, "UP", Vector3(0, 1, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR3, "DOWN", Vector3(0, -1, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR3, "FORWARD", Vector3(0, 0, -1)); - _VariantCall::add_variant_constant(Variant::VECTOR3, "BACK", Vector3(0, 0, 1)); - - _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_X", Vector3i::AXIS_X); - _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Y", Vector3i::AXIS_Y); - _VariantCall::add_constant(Variant::VECTOR3I, "AXIS_Z", Vector3i::AXIS_Z); - - _VariantCall::add_variant_constant(Variant::VECTOR3I, "ZERO", Vector3i(0, 0, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR3I, "ONE", Vector3i(1, 1, 1)); - _VariantCall::add_variant_constant(Variant::VECTOR3I, "LEFT", Vector3i(-1, 0, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR3I, "RIGHT", Vector3i(1, 0, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR3I, "UP", Vector3i(0, 1, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR3I, "DOWN", Vector3i(0, -1, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR3I, "FORWARD", Vector3i(0, 0, -1)); - _VariantCall::add_variant_constant(Variant::VECTOR3I, "BACK", Vector3i(0, 0, 1)); - - _VariantCall::add_constant(Variant::VECTOR2, "AXIS_X", Vector2::AXIS_X); - _VariantCall::add_constant(Variant::VECTOR2, "AXIS_Y", Vector2::AXIS_Y); - - _VariantCall::add_constant(Variant::VECTOR2I, "AXIS_X", Vector2i::AXIS_X); - _VariantCall::add_constant(Variant::VECTOR2I, "AXIS_Y", Vector2i::AXIS_Y); - - _VariantCall::add_variant_constant(Variant::VECTOR2, "ZERO", Vector2(0, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR2, "ONE", Vector2(1, 1)); - _VariantCall::add_variant_constant(Variant::VECTOR2, "INF", Vector2(Math_INF, Math_INF)); - _VariantCall::add_variant_constant(Variant::VECTOR2, "LEFT", Vector2(-1, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR2, "RIGHT", Vector2(1, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR2, "UP", Vector2(0, -1)); - _VariantCall::add_variant_constant(Variant::VECTOR2, "DOWN", Vector2(0, 1)); - - _VariantCall::add_variant_constant(Variant::VECTOR2I, "ZERO", Vector2i(0, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR2I, "ONE", Vector2i(1, 1)); - _VariantCall::add_variant_constant(Variant::VECTOR2I, "LEFT", Vector2i(-1, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR2I, "RIGHT", Vector2i(1, 0)); - _VariantCall::add_variant_constant(Variant::VECTOR2I, "UP", Vector2i(0, -1)); - _VariantCall::add_variant_constant(Variant::VECTOR2I, "DOWN", Vector2i(0, 1)); - - _VariantCall::add_variant_constant(Variant::TRANSFORM2D, "IDENTITY", Transform2D()); - _VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_X", Transform2D(-1, 0, 0, 1, 0, 0)); - _VariantCall::add_variant_constant(Variant::TRANSFORM2D, "FLIP_Y", Transform2D(1, 0, 0, -1, 0, 0)); - - Transform identity_transform = Transform(); - Transform flip_x_transform = Transform(-1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0); - Transform flip_y_transform = Transform(1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0); - Transform flip_z_transform = Transform(1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0); - _VariantCall::add_variant_constant(Variant::TRANSFORM, "IDENTITY", identity_transform); - _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_X", flip_x_transform); - _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_Y", flip_y_transform); - _VariantCall::add_variant_constant(Variant::TRANSFORM, "FLIP_Z", flip_z_transform); - - Basis identity_basis = Basis(); - Basis flip_x_basis = Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1); - Basis flip_y_basis = Basis(1, 0, 0, 0, -1, 0, 0, 0, 1); - Basis flip_z_basis = Basis(1, 0, 0, 0, 1, 0, 0, 0, -1); - _VariantCall::add_variant_constant(Variant::BASIS, "IDENTITY", identity_basis); - _VariantCall::add_variant_constant(Variant::BASIS, "FLIP_X", flip_x_basis); - _VariantCall::add_variant_constant(Variant::BASIS, "FLIP_Y", flip_y_basis); - _VariantCall::add_variant_constant(Variant::BASIS, "FLIP_Z", flip_z_basis); - - _VariantCall::add_variant_constant(Variant::PLANE, "PLANE_YZ", Plane(Vector3(1, 0, 0), 0)); - _VariantCall::add_variant_constant(Variant::PLANE, "PLANE_XZ", Plane(Vector3(0, 1, 0), 0)); - _VariantCall::add_variant_constant(Variant::PLANE, "PLANE_XY", Plane(Vector3(0, 0, 1), 0)); - - _VariantCall::add_variant_constant(Variant::QUAT, "IDENTITY", Quat(0, 0, 0, 1)); -} - -void unregister_variant_methods() { - memdelete_arr(_VariantCall::type_funcs); - memdelete_arr(_VariantCall::construct_funcs); - memdelete_arr(_VariantCall::constant_data); -} diff --git a/core/variant_internal.h b/core/variant_internal.h deleted file mode 100644 index 0e0a1e398f..0000000000 --- a/core/variant_internal.h +++ /dev/null @@ -1,118 +0,0 @@ -/*************************************************************************/ -/* variant_internal.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef VARIANT_INTERNAL_H -#define VARIANT_INTERNAL_H - -#include "variant.h" - -// For use when you want to access the internal pointer of a Variant directly. -// Use with caution. You need to be sure that the type is correct. -class VariantInternal { -public: - // Set type. - _FORCE_INLINE_ static void initialize(Variant *v, Variant::Type p_type) { v->type = p_type; } - - // Atomic types. - _FORCE_INLINE_ static bool *get_bool(Variant *v) { return &v->_data._bool; } - _FORCE_INLINE_ static const bool *get_bool(const Variant *v) { return &v->_data._bool; } - _FORCE_INLINE_ static int64_t *get_int(Variant *v) { return &v->_data._int; } - _FORCE_INLINE_ static const int64_t *get_int(const Variant *v) { return &v->_data._int; } - _FORCE_INLINE_ static double *get_float(Variant *v) { return &v->_data._float; } - _FORCE_INLINE_ static const double *get_float(const Variant *v) { return &v->_data._float; } - _FORCE_INLINE_ static String *get_string(Variant *v) { return reinterpret_cast<String *>(v->_data._mem); } - _FORCE_INLINE_ static const String *get_string(const Variant *v) { return reinterpret_cast<const String *>(v->_data._mem); } - - // Math types. - _FORCE_INLINE_ static Vector2 *get_vector2(Variant *v) { return reinterpret_cast<Vector2 *>(v->_data._mem); } - _FORCE_INLINE_ static const Vector2 *get_vector2(const Variant *v) { return reinterpret_cast<const Vector2 *>(v->_data._mem); } - _FORCE_INLINE_ static Vector2i *get_vector2i(Variant *v) { return reinterpret_cast<Vector2i *>(v->_data._mem); } - _FORCE_INLINE_ static const Vector2i *get_vector2i(const Variant *v) { return reinterpret_cast<const Vector2i *>(v->_data._mem); } - _FORCE_INLINE_ static Rect2 *get_rect2(Variant *v) { return reinterpret_cast<Rect2 *>(v->_data._mem); } - _FORCE_INLINE_ static const Rect2 *get_rect2(const Variant *v) { return reinterpret_cast<const Rect2 *>(v->_data._mem); } - _FORCE_INLINE_ static Rect2i *get_rect2i(Variant *v) { return reinterpret_cast<Rect2i *>(v->_data._mem); } - _FORCE_INLINE_ static const Rect2i *get_rect2i(const Variant *v) { return reinterpret_cast<const Rect2i *>(v->_data._mem); } - _FORCE_INLINE_ static Vector3 *get_vector3(Variant *v) { return reinterpret_cast<Vector3 *>(v->_data._mem); } - _FORCE_INLINE_ static const Vector3 *get_vector3(const Variant *v) { return reinterpret_cast<const Vector3 *>(v->_data._mem); } - _FORCE_INLINE_ static Vector3i *get_vector3i(Variant *v) { return reinterpret_cast<Vector3i *>(v->_data._mem); } - _FORCE_INLINE_ static const Vector3i *get_vector3i(const Variant *v) { return reinterpret_cast<const Vector3i *>(v->_data._mem); } - _FORCE_INLINE_ static Transform2D *get_transform2d(Variant *v) { return v->_data._transform2d; } - _FORCE_INLINE_ static const Transform2D *get_transform2d(const Variant *v) { return v->_data._transform2d; } - _FORCE_INLINE_ static Plane *get_plane(Variant *v) { return reinterpret_cast<Plane *>(v->_data._mem); } - _FORCE_INLINE_ static const Plane *get_plane(const Variant *v) { return reinterpret_cast<const Plane *>(v->_data._mem); } - _FORCE_INLINE_ static Quat *get_quat(Variant *v) { return reinterpret_cast<Quat *>(v->_data._mem); } - _FORCE_INLINE_ static const Quat *get_quat(const Variant *v) { return reinterpret_cast<const Quat *>(v->_data._mem); } - _FORCE_INLINE_ static ::AABB *get_aabb(Variant *v) { return v->_data._aabb; } - _FORCE_INLINE_ static const ::AABB *get_aabb(const Variant *v) { return v->_data._aabb; } - _FORCE_INLINE_ static Basis *get_basis(Variant *v) { return v->_data._basis; } - _FORCE_INLINE_ static const Basis *get_basis(const Variant *v) { return v->_data._basis; } - _FORCE_INLINE_ static Transform *get_transform(Variant *v) { return v->_data._transform; } - _FORCE_INLINE_ static const Transform *get_transform(const Variant *v) { return v->_data._transform; } - - // Misc types. - _FORCE_INLINE_ static Color *get_color(Variant *v) { return reinterpret_cast<Color *>(v->_data._mem); } - _FORCE_INLINE_ static const Color *get_color(const Variant *v) { return reinterpret_cast<const Color *>(v->_data._mem); } - _FORCE_INLINE_ static StringName *get_string_name(Variant *v) { return reinterpret_cast<StringName *>(v->_data._mem); } - _FORCE_INLINE_ static const StringName *get_string_name(const Variant *v) { return reinterpret_cast<const StringName *>(v->_data._mem); } - _FORCE_INLINE_ static NodePath *get_node_path(Variant *v) { return reinterpret_cast<NodePath *>(v->_data._mem); } - _FORCE_INLINE_ static const NodePath *get_node_path(const Variant *v) { return reinterpret_cast<const NodePath *>(v->_data._mem); } - _FORCE_INLINE_ static RID *get_rid(Variant *v) { return reinterpret_cast<RID *>(v->_data._mem); } - _FORCE_INLINE_ static const RID *get_rid(const Variant *v) { return reinterpret_cast<const RID *>(v->_data._mem); } - _FORCE_INLINE_ static Callable *get_callable(Variant *v) { return reinterpret_cast<Callable *>(v->_data._mem); } - _FORCE_INLINE_ static const Callable *get_callable(const Variant *v) { return reinterpret_cast<const Callable *>(v->_data._mem); } - _FORCE_INLINE_ static Signal *get_signal(Variant *v) { return reinterpret_cast<Signal *>(v->_data._mem); } - _FORCE_INLINE_ static const Signal *get_signal(const Variant *v) { return reinterpret_cast<const Signal *>(v->_data._mem); } - _FORCE_INLINE_ static Dictionary *get_dictionary(Variant *v) { return reinterpret_cast<Dictionary *>(v->_data._mem); } - _FORCE_INLINE_ static const Dictionary *get_dictionary(const Variant *v) { return reinterpret_cast<const Dictionary *>(v->_data._mem); } - _FORCE_INLINE_ static Array *get_array(Variant *v) { return reinterpret_cast<Array *>(v->_data._mem); } - _FORCE_INLINE_ static const Array *get_array(const Variant *v) { return reinterpret_cast<const Array *>(v->_data._mem); } - - // Typed arrays. - _FORCE_INLINE_ static PackedByteArray *get_byte_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<uint8_t> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static const PackedByteArray *get_byte_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<uint8_t> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static PackedInt32Array *get_int32_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<int32_t> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static const PackedInt32Array *get_int32_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<int32_t> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static PackedInt64Array *get_int64_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<int64_t> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static const PackedInt64Array *get_int64_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<int64_t> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static PackedFloat32Array *get_float32_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<float> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static const PackedFloat32Array *get_float32_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<float> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static PackedFloat64Array *get_float64_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<double> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static const PackedFloat64Array *get_float64_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<double> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static PackedStringArray *get_string_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<String> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static const PackedStringArray *get_string_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<String> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static PackedVector2Array *get_vector2_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<Vector2> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static const PackedVector2Array *get_vector2_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<Vector2> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static PackedVector3Array *get_vector3_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<Vector3> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static const PackedVector3Array *get_vector3_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<Vector3> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static PackedColorArray *get_color_array(Variant *v) { return &static_cast<Variant::PackedArrayRef<Color> *>(v->_data.packed_array)->array; } - _FORCE_INLINE_ static const PackedColorArray *get_color_array(const Variant *v) { return &static_cast<const Variant::PackedArrayRef<Color> *>(v->_data.packed_array)->array; } -}; - -#endif // VARIANT_INTERNAL_H diff --git a/core/variant_op.cpp b/core/variant_op.cpp deleted file mode 100644 index 533b056f91..0000000000 --- a/core/variant_op.cpp +++ /dev/null @@ -1,4608 +0,0 @@ -/*************************************************************************/ -/* variant_op.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "variant.h" - -#include "core/core_string_names.h" -#include "core/debugger/engine_debugger.h" -#include "core/object.h" - -#define CASE_TYPE_ALL(PREFIX, OP) \ - CASE_TYPE(PREFIX, OP, INT) \ - CASE_TYPE_ALL_BUT_INT(PREFIX, OP) - -#define CASE_TYPE_ALL_BUT_INT(PREFIX, OP) \ - CASE_TYPE(PREFIX, OP, NIL) \ - CASE_TYPE(PREFIX, OP, BOOL) \ - CASE_TYPE(PREFIX, OP, FLOAT) \ - CASE_TYPE(PREFIX, OP, STRING) \ - CASE_TYPE(PREFIX, OP, VECTOR2) \ - CASE_TYPE(PREFIX, OP, VECTOR2I) \ - CASE_TYPE(PREFIX, OP, RECT2) \ - CASE_TYPE(PREFIX, OP, RECT2I) \ - CASE_TYPE(PREFIX, OP, VECTOR3) \ - CASE_TYPE(PREFIX, OP, VECTOR3I) \ - CASE_TYPE(PREFIX, OP, TRANSFORM2D) \ - CASE_TYPE(PREFIX, OP, PLANE) \ - CASE_TYPE(PREFIX, OP, QUAT) \ - CASE_TYPE(PREFIX, OP, AABB) \ - CASE_TYPE(PREFIX, OP, BASIS) \ - CASE_TYPE(PREFIX, OP, TRANSFORM) \ - CASE_TYPE(PREFIX, OP, COLOR) \ - CASE_TYPE(PREFIX, OP, STRING_NAME) \ - CASE_TYPE(PREFIX, OP, NODE_PATH) \ - CASE_TYPE(PREFIX, OP, _RID) \ - CASE_TYPE(PREFIX, OP, OBJECT) \ - CASE_TYPE(PREFIX, OP, CALLABLE) \ - CASE_TYPE(PREFIX, OP, SIGNAL) \ - CASE_TYPE(PREFIX, OP, DICTIONARY) \ - CASE_TYPE(PREFIX, OP, ARRAY) \ - CASE_TYPE(PREFIX, OP, PACKED_BYTE_ARRAY) \ - CASE_TYPE(PREFIX, OP, PACKED_INT32_ARRAY) \ - CASE_TYPE(PREFIX, OP, PACKED_INT64_ARRAY) \ - CASE_TYPE(PREFIX, OP, PACKED_FLOAT32_ARRAY) \ - CASE_TYPE(PREFIX, OP, PACKED_FLOAT64_ARRAY) \ - CASE_TYPE(PREFIX, OP, PACKED_STRING_ARRAY) \ - CASE_TYPE(PREFIX, OP, PACKED_VECTOR2_ARRAY) \ - CASE_TYPE(PREFIX, OP, PACKED_VECTOR3_ARRAY) \ - CASE_TYPE(PREFIX, OP, PACKED_COLOR_ARRAY) - -#ifdef __GNUC__ -#define TYPE(PREFIX, OP, TYPE) &&PREFIX##_##OP##_##TYPE - -/* clang-format off */ -#define TYPES(PREFIX, OP) { \ - TYPE(PREFIX, OP, NIL), \ - TYPE(PREFIX, OP, BOOL), \ - TYPE(PREFIX, OP, INT), \ - TYPE(PREFIX, OP, FLOAT), \ - TYPE(PREFIX, OP, STRING), \ - TYPE(PREFIX, OP, VECTOR2), \ - TYPE(PREFIX, OP, VECTOR2I), \ - TYPE(PREFIX, OP, RECT2), \ - TYPE(PREFIX, OP, RECT2I), \ - TYPE(PREFIX, OP, VECTOR3), \ - TYPE(PREFIX, OP, VECTOR3I), \ - TYPE(PREFIX, OP, TRANSFORM2D), \ - TYPE(PREFIX, OP, PLANE), \ - TYPE(PREFIX, OP, QUAT), \ - TYPE(PREFIX, OP, AABB), \ - TYPE(PREFIX, OP, BASIS), \ - TYPE(PREFIX, OP, TRANSFORM), \ - TYPE(PREFIX, OP, COLOR), \ - TYPE(PREFIX, OP, STRING_NAME), \ - TYPE(PREFIX, OP, NODE_PATH), \ - TYPE(PREFIX, OP, _RID), \ - TYPE(PREFIX, OP, OBJECT), \ - TYPE(PREFIX, OP, CALLABLE), \ - TYPE(PREFIX, OP, SIGNAL), \ - TYPE(PREFIX, OP, DICTIONARY), \ - TYPE(PREFIX, OP, ARRAY), \ - TYPE(PREFIX, OP, PACKED_BYTE_ARRAY), \ - TYPE(PREFIX, OP, PACKED_INT32_ARRAY), \ - TYPE(PREFIX, OP, PACKED_INT64_ARRAY), \ - TYPE(PREFIX, OP, PACKED_FLOAT32_ARRAY), \ - TYPE(PREFIX, OP, PACKED_FLOAT64_ARRAY), \ - TYPE(PREFIX, OP, PACKED_STRING_ARRAY), \ - TYPE(PREFIX, OP, PACKED_VECTOR2_ARRAY), \ - TYPE(PREFIX, OP, PACKED_VECTOR3_ARRAY), \ - TYPE(PREFIX, OP, PACKED_COLOR_ARRAY), \ -} - -/* clang-format on */ - -#define CASES(PREFIX) static const void *switch_table_##PREFIX[Variant::OP_MAX][Variant::VARIANT_MAX] = { \ - TYPES(PREFIX, OP_EQUAL), \ - TYPES(PREFIX, OP_NOT_EQUAL), \ - TYPES(PREFIX, OP_LESS), \ - TYPES(PREFIX, OP_LESS_EQUAL), \ - TYPES(PREFIX, OP_GREATER), \ - TYPES(PREFIX, OP_GREATER_EQUAL), \ - TYPES(PREFIX, OP_ADD), \ - TYPES(PREFIX, OP_SUBTRACT), \ - TYPES(PREFIX, OP_MULTIPLY), \ - TYPES(PREFIX, OP_DIVIDE), \ - TYPES(PREFIX, OP_NEGATE), \ - TYPES(PREFIX, OP_POSITIVE), \ - TYPES(PREFIX, OP_MODULE), \ - TYPES(PREFIX, OP_STRING_CONCAT), \ - TYPES(PREFIX, OP_SHIFT_LEFT), \ - TYPES(PREFIX, OP_SHIFT_RIGHT), \ - TYPES(PREFIX, OP_BIT_AND), \ - TYPES(PREFIX, OP_BIT_OR), \ - TYPES(PREFIX, OP_BIT_XOR), \ - TYPES(PREFIX, OP_BIT_NEGATE), \ - TYPES(PREFIX, OP_AND), \ - TYPES(PREFIX, OP_OR), \ - TYPES(PREFIX, OP_XOR), \ - TYPES(PREFIX, OP_NOT), \ - TYPES(PREFIX, OP_IN), \ -} - -#define SWITCH(PREFIX, op, val) goto *switch_table_##PREFIX[op][val]; -#define SWITCH_OP(PREFIX, OP, val) -#define CASE_TYPE(PREFIX, OP, TYPE) PREFIX##_##OP##_##TYPE: - -#else -#define CASES(PREFIX) -#define SWITCH(PREFIX, op, val) switch (op) -#define SWITCH_OP(PREFIX, OP, val) \ - case OP: \ - switch (val) -#define CASE_TYPE(PREFIX, OP, TYPE) case TYPE: -#endif - -Variant::operator bool() const { - return booleanize(); -} - -// We consider all uninitialized or empty types to be false based on the type's -// zeroiness. -bool Variant::booleanize() const { - return !is_zero(); -} - -#define _RETURN(m_what) \ - { \ - r_ret = m_what; \ - return; \ - } - -#define _RETURN_FAIL \ - { \ - r_valid = false; \ - return; \ - } - -#define DEFAULT_OP_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == INT) \ - _RETURN(p_a._data.m_type m_op p_b._data._int); \ - if (p_b.type == FLOAT) \ - _RETURN(p_a._data.m_type m_op p_b._data._float); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_NUM_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == INT) \ - _RETURN(p_a._data.m_type m_op p_b._data._int); \ - if (p_b.type == FLOAT) \ - _RETURN(p_a._data.m_type m_op p_b._data._float); \ - if (p_b.type == NIL) \ - _RETURN(!(p_b.type m_op NIL)); \ - \ - _RETURN_FAIL \ - } - -#ifdef DEBUG_ENABLED -#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == INT) { \ - if (p_b._data._int == 0) { \ - r_valid = false; \ - _RETURN("Division By Zero"); \ - } \ - _RETURN(p_a._data.m_type / p_b._data._int); \ - } \ - if (p_b.type == FLOAT) { \ - if (p_b._data._float == 0) { \ - r_valid = false; \ - _RETURN("Division By Zero"); \ - } \ - _RETURN(p_a._data.m_type / p_b._data._float); \ - } \ - \ - _RETURN_FAIL \ - } -#else -#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == INT) \ - _RETURN(p_a._data.m_type / p_b._data._int); \ - if (p_b.type == FLOAT) \ - _RETURN(p_a._data.m_type / p_b._data._float); \ - \ - _RETURN_FAIL \ - } -#endif - -#define DEFAULT_OP_NUM_NEG(m_prefix, m_op_name, m_name, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - _RETURN(-p_a._data.m_type); \ - } - -#define DEFAULT_OP_NUM_POS(m_prefix, m_op_name, m_name, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - _RETURN(p_a._data.m_type); \ - } - -#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == INT) \ - _RETURN(p_a._data.m_type m_op p_b._data._int); \ - if (p_b.type == FLOAT) \ - _RETURN(p_a._data.m_type m_op p_b._data._float); \ - if (p_b.type == VECTOR2) \ - _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \ - if (p_b.type == VECTOR3) \ - _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \ - if (p_b.type == VECTOR2I) \ - _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2i *>(p_b._data._mem)); \ - if (p_b.type == VECTOR3I) \ - _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3i *>(p_b._data._mem)); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_STR_REV(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == STRING) \ - _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const String *>(p_a._data._mem)); \ - if (p_b.type == STRING_NAME) \ - _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const StringName *>(p_a._data._mem)); \ - if (p_b.type == NODE_PATH) \ - _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const NodePath *>(p_a._data._mem)); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_STR(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == STRING) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ - if (p_b.type == STRING_NAME) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \ - if (p_b.type == NODE_PATH) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_STR_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == STRING) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ - if (p_b.type == STRING_NAME) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \ - if (p_b.type == NODE_PATH) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \ - if (p_b.type == NIL) \ - _RETURN(!(p_b.type m_op NIL)); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_STR_NULL_NP(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == STRING) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ - if (p_b.type == NODE_PATH) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \ - if (p_b.type == NIL) \ - _RETURN(!(p_b.type m_op NIL)); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_STR_NULL_SN(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == STRING) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \ - if (p_b.type == STRING_NAME) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const StringName *>(p_b._data._mem)); \ - if (p_b.type == NIL) \ - _RETURN(!(p_b.type m_op NIL)); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_LOCALMEM_REV(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == m_name) \ - _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const m_type *>(p_a._data._mem)); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_LOCALMEM(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == m_name) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_LOCALMEM_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == m_name) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \ - if (p_b.type == NIL) \ - _RETURN(!(p_b.type m_op NIL)); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_LOCALMEM_NEG(m_prefix, m_op_name, m_name, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - _RETURN(-*reinterpret_cast<const m_type *>(p_a._data._mem)); \ - } - -#define DEFAULT_OP_LOCALMEM_POS(m_prefix, m_op_name, m_name, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem)); \ - } - -#define DEFAULT_OP_LOCALMEM_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == m_name) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \ - if (p_b.type == INT) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._int); \ - if (p_b.type == FLOAT) \ - _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._float); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_PTR(m_op, m_name, m_sub) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == m_name) \ - _RETURN(p_a._data.m_sub m_op p_b._data.m_sub); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_PTRREF(m_prefix, m_op_name, m_name, m_op, m_sub) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == m_name) \ - _RETURN(*p_a._data.m_sub m_op *p_b._data.m_sub); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_PTRREF_NULL(m_prefix, m_op_name, m_name, m_op, m_sub) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == m_name) \ - _RETURN(*p_a._data.m_sub m_op *p_b._data.m_sub); \ - if (p_b.type == NIL) \ - _RETURN(!(p_b.type m_op NIL)); \ - \ - _RETURN_FAIL \ - } - -#define DEFAULT_OP_ARRAY_EQ(m_prefix, m_op_name, m_name, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == NIL) \ - _RETURN(false) \ - DEFAULT_OP_ARRAY_OP_BODY(m_prefix, m_op_name, m_name, m_type, !=, !=, true, false, false) \ - } - -#define DEFAULT_OP_ARRAY_NEQ(m_prefix, m_op_name, m_name, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_b.type == NIL) \ - _RETURN(true) \ - DEFAULT_OP_ARRAY_OP_BODY(m_prefix, m_op_name, m_name, m_type, !=, !=, false, true, true) \ - } - -#define DEFAULT_OP_ARRAY_LT(m_prefix, m_op_name, m_name, m_type) \ - DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, <, !=, false, a_len < array_b.size(), true) - -#define DEFAULT_OP_ARRAY_GT(m_prefix, m_op_name, m_name, m_type) \ - DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, >, !=, false, a_len < array_b.size(), true) - -#define DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - DEFAULT_OP_ARRAY_OP_BODY(m_prefix, m_op_name, m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \ - } - -#define DEFAULT_OP_ARRAY_OP_BODY(m_prefix, m_op_name, m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \ - if (p_a.type != p_b.type) \ - _RETURN_FAIL \ - \ - const Vector<m_type> &array_a = PackedArrayRef<m_type>::get_array(p_a._data.packed_array); \ - const Vector<m_type> &array_b = PackedArrayRef<m_type>::get_array(p_b._data.packed_array); \ - \ - int a_len = array_a.size(); \ - if (a_len m_opa array_b.size()) { \ - _RETURN(m_ret_s); \ - } else { \ - const m_type *ra = array_a.ptr(); \ - const m_type *rb = array_b.ptr(); \ - \ - for (int i = 0; i < a_len; i++) { \ - if (ra[i] m_opb rb[i]) \ - _RETURN(m_ret_f); \ - } \ - \ - _RETURN(m_ret_def); \ - } - -#define DEFAULT_OP_ARRAY_ADD(m_prefix, m_op_name, m_name, m_type) \ - CASE_TYPE(m_prefix, m_op_name, m_name) { \ - if (p_a.type != p_b.type) \ - _RETURN_FAIL; \ - \ - const Vector<m_type> &array_a = PackedArrayRef<m_type>::get_array(p_a._data.packed_array); \ - const Vector<m_type> &array_b = PackedArrayRef<m_type>::get_array(p_b._data.packed_array); \ - Vector<m_type> sum = array_a; \ - sum.append_array(array_b); \ - _RETURN(sum); \ - } - -void Variant::evaluate(const Operator &p_op, const Variant &p_a, - const Variant &p_b, Variant &r_ret, bool &r_valid) { - CASES(math); - r_valid = true; - - SWITCH(math, p_op, p_a.type) { - SWITCH_OP(math, OP_EQUAL, p_a.type) { - CASE_TYPE(math, OP_EQUAL, NIL) { - if (p_b.type == NIL) - _RETURN(true); - if (p_b.type == OBJECT) - _RETURN(p_b._get_obj().obj == nullptr); - - _RETURN(false); - } - - CASE_TYPE(math, OP_EQUAL, BOOL) { - if (p_b.type != BOOL) { - if (p_b.type == NIL) - _RETURN(false); - _RETURN_FAIL; - } - - _RETURN(p_a._data._bool == p_b._data._bool); - } - - CASE_TYPE(math, OP_EQUAL, OBJECT) { - if (p_b.type == OBJECT) - _RETURN((p_a._get_obj().obj == p_b._get_obj().obj)); - if (p_b.type == NIL) - _RETURN(p_a._get_obj().obj == nullptr); - - _RETURN_FAIL; - } - - DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, CALLABLE, ==, Callable); - DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, SIGNAL, ==, Signal); - - CASE_TYPE(math, OP_EQUAL, DICTIONARY) { - if (p_b.type != DICTIONARY) { - if (p_b.type == NIL) - _RETURN(false); - _RETURN_FAIL; - } - - const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem); - const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem); - - _RETURN(*arr_a == *arr_b); - } - - CASE_TYPE(math, OP_EQUAL, ARRAY) { - if (p_b.type != ARRAY) { - if (p_b.type == NIL) - _RETURN(false); - _RETURN_FAIL; - } - const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); - const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - - int l = arr_a->size(); - if (arr_b->size() != l) - _RETURN(false); - for (int i = 0; i < l; i++) { - if (!((*arr_a)[i] == (*arr_b)[i])) { - _RETURN(false); - } - } - - _RETURN(true); - } - - DEFAULT_OP_NUM_NULL(math, OP_EQUAL, INT, ==, _int); - DEFAULT_OP_NUM_NULL(math, OP_EQUAL, FLOAT, ==, _float); - DEFAULT_OP_STR_NULL(math, OP_EQUAL, STRING, ==, String); - DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR2, ==, Vector2); - DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR2I, ==, Vector2i); - DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, RECT2, ==, Rect2); - DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, RECT2I, ==, Rect2i); - DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, TRANSFORM2D, ==, _transform2d); - DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR3, ==, Vector3); - DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR3I, ==, Vector3i); - DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, PLANE, ==, Plane); - DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, QUAT, ==, Quat); - DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, AABB, ==, _aabb); - DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, BASIS, ==, _basis); - DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, TRANSFORM, ==, _transform); - DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, COLOR, ==, Color); - DEFAULT_OP_STR_NULL_SN(math, OP_EQUAL, STRING_NAME, ==, StringName); - DEFAULT_OP_STR_NULL_NP(math, OP_EQUAL, NODE_PATH, ==, NodePath); - DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, _RID, ==, RID); - - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_INT32_ARRAY, int32_t); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_INT64_ARRAY, int64_t); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_FLOAT32_ARRAY, float); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_FLOAT64_ARRAY, double); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_VECTOR2_ARRAY, Vector2); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, PACKED_COLOR_ARRAY, Color); - } - - SWITCH_OP(math, OP_NOT_EQUAL, p_a.type) { - CASE_TYPE(math, OP_NOT_EQUAL, NIL) { - if (p_b.type == NIL) - _RETURN(false); - if (p_b.type == OBJECT) - _RETURN(p_b._get_obj().obj != nullptr); - - _RETURN(true); - } - - CASE_TYPE(math, OP_NOT_EQUAL, BOOL) { - if (p_b.type != BOOL) { - if (p_b.type == NIL) - _RETURN(true); - - _RETURN_FAIL; - } - - _RETURN(p_a._data._bool != p_b._data._bool); - } - - CASE_TYPE(math, OP_NOT_EQUAL, OBJECT) { - if (p_b.type == OBJECT) - _RETURN((p_a._get_obj().obj != p_b._get_obj().obj)); - if (p_b.type == NIL) - _RETURN(p_a._get_obj().obj != nullptr); - - _RETURN_FAIL; - } - - DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, CALLABLE, !=, Callable); - DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, SIGNAL, !=, Signal); - - CASE_TYPE(math, OP_NOT_EQUAL, DICTIONARY) { - if (p_b.type != DICTIONARY) { - if (p_b.type == NIL) - _RETURN(true); - _RETURN_FAIL; - } - - const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem); - const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem); - - _RETURN(*arr_a != *arr_b); - } - - CASE_TYPE(math, OP_NOT_EQUAL, ARRAY) { - if (p_b.type != ARRAY) { - if (p_b.type == NIL) - _RETURN(true); - - _RETURN_FAIL; - } - - const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); - const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - - int l = arr_a->size(); - if (arr_b->size() != l) - _RETURN(true); - for (int i = 0; i < l; i++) { - if (((*arr_a)[i] != (*arr_b)[i])) { - _RETURN(true); - } - } - - _RETURN(false); - } - - DEFAULT_OP_NUM_NULL(math, OP_NOT_EQUAL, INT, !=, _int); - DEFAULT_OP_NUM_NULL(math, OP_NOT_EQUAL, FLOAT, !=, _float); - DEFAULT_OP_STR_NULL(math, OP_NOT_EQUAL, STRING, !=, String); - DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR2, !=, Vector2); - DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR2I, !=, Vector2i); - DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, RECT2, !=, Rect2); - DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, RECT2I, !=, Rect2i); - DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, TRANSFORM2D, !=, _transform2d); - DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR3, !=, Vector3); - DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR3I, !=, Vector3i); - DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, PLANE, !=, Plane); - DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, QUAT, !=, Quat); - DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, AABB, !=, _aabb); - DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, BASIS, !=, _basis); - DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, TRANSFORM, !=, _transform); - DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, COLOR, !=, Color); - DEFAULT_OP_STR_NULL_SN(math, OP_NOT_EQUAL, STRING_NAME, !=, StringName); - DEFAULT_OP_STR_NULL_NP(math, OP_NOT_EQUAL, NODE_PATH, !=, NodePath); - DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, _RID, !=, RID); - - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_INT32_ARRAY, int32_t); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_INT64_ARRAY, int64_t); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_FLOAT32_ARRAY, float); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_FLOAT64_ARRAY, double); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_VECTOR2_ARRAY, Vector2); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, PACKED_COLOR_ARRAY, Color); - } - - SWITCH_OP(math, OP_LESS, p_a.type) { - CASE_TYPE(math, OP_LESS, BOOL) { - if (p_b.type != BOOL) - _RETURN_FAIL; - - if (p_a._data._bool == p_b._data._bool) - _RETURN(false); - - if (p_a._data._bool && !p_b._data._bool) - _RETURN(false); - - _RETURN(true); - } - - CASE_TYPE(math, OP_LESS, OBJECT) { - if (p_b.type != OBJECT) - _RETURN_FAIL; - _RETURN((p_a._get_obj().obj < p_b._get_obj().obj)); - } - - DEFAULT_OP_LOCALMEM_NULL(math, OP_LESS, CALLABLE, <, Callable); - DEFAULT_OP_LOCALMEM_NULL(math, OP_LESS, SIGNAL, <, Signal); - - CASE_TYPE(math, OP_LESS, ARRAY) { - if (p_b.type != ARRAY) - _RETURN_FAIL; - - const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); - const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - - int l = arr_a->size(); - if (arr_b->size() < l) - _RETURN(false); - for (int i = 0; i < l; i++) { - if (!((*arr_a)[i] < (*arr_b)[i])) { - _RETURN(true); - } - } - - _RETURN(false); - } - - DEFAULT_OP_NUM(math, OP_LESS, INT, <, _int); - DEFAULT_OP_NUM(math, OP_LESS, FLOAT, <, _float); - DEFAULT_OP_STR(math, OP_LESS, STRING, <, String); - DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR2, <, Vector2); - DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR2I, <, Vector2i); - DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR3, <, Vector3); - DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR3I, <, Vector3i); - DEFAULT_OP_LOCALMEM(math, OP_LESS, _RID, <, RID); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_INT32_ARRAY, int32_t); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_INT64_ARRAY, int64_t); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_FLOAT32_ARRAY, float); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_FLOAT64_ARRAY, double); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_VECTOR2_ARRAY, Vector3); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_LT(math, OP_LESS, PACKED_COLOR_ARRAY, Color); - - CASE_TYPE(math, OP_LESS, NIL) - CASE_TYPE(math, OP_LESS, RECT2) - CASE_TYPE(math, OP_LESS, RECT2I) - CASE_TYPE(math, OP_LESS, TRANSFORM2D) - CASE_TYPE(math, OP_LESS, PLANE) - CASE_TYPE(math, OP_LESS, QUAT) - CASE_TYPE(math, OP_LESS, AABB) - CASE_TYPE(math, OP_LESS, BASIS) - CASE_TYPE(math, OP_LESS, TRANSFORM) - CASE_TYPE(math, OP_LESS, COLOR) - CASE_TYPE(math, OP_LESS, STRING_NAME) - CASE_TYPE(math, OP_LESS, NODE_PATH) - CASE_TYPE(math, OP_LESS, DICTIONARY) - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_LESS_EQUAL, p_a.type) { - CASE_TYPE(math, OP_LESS_EQUAL, OBJECT) { - if (p_b.type != OBJECT) - _RETURN_FAIL; - _RETURN((p_a._get_obj().obj <= p_b._get_obj().obj)); - } - - DEFAULT_OP_NUM(math, OP_LESS_EQUAL, INT, <=, _int); - DEFAULT_OP_NUM(math, OP_LESS_EQUAL, FLOAT, <=, _float); - DEFAULT_OP_STR(math, OP_LESS_EQUAL, STRING, <=, String); - DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR2, <=, Vector2); - DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR2I, <=, Vector2i); - DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR3, <=, Vector3); - DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR3I, <=, Vector3i); - DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, _RID, <=, RID); - - CASE_TYPE(math, OP_LESS_EQUAL, NIL) - CASE_TYPE(math, OP_LESS_EQUAL, BOOL) - CASE_TYPE(math, OP_LESS_EQUAL, RECT2) - CASE_TYPE(math, OP_LESS_EQUAL, RECT2I) - CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM2D) - CASE_TYPE(math, OP_LESS_EQUAL, PLANE) - CASE_TYPE(math, OP_LESS_EQUAL, QUAT) - CASE_TYPE(math, OP_LESS_EQUAL, AABB) - CASE_TYPE(math, OP_LESS_EQUAL, BASIS) - CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM) - CASE_TYPE(math, OP_LESS_EQUAL, COLOR) - CASE_TYPE(math, OP_LESS_EQUAL, STRING_NAME) - CASE_TYPE(math, OP_LESS_EQUAL, NODE_PATH) - CASE_TYPE(math, OP_LESS_EQUAL, CALLABLE) - CASE_TYPE(math, OP_LESS_EQUAL, SIGNAL) - - CASE_TYPE(math, OP_LESS_EQUAL, DICTIONARY) - CASE_TYPE(math, OP_LESS_EQUAL, ARRAY) - CASE_TYPE(math, OP_LESS_EQUAL, PACKED_BYTE_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, PACKED_INT32_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, PACKED_INT64_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, PACKED_FLOAT32_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, PACKED_FLOAT64_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, PACKED_STRING_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, PACKED_VECTOR2_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, PACKED_VECTOR3_ARRAY); - CASE_TYPE(math, OP_LESS_EQUAL, PACKED_COLOR_ARRAY); - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_GREATER, p_a.type) { - CASE_TYPE(math, OP_GREATER, BOOL) { - if (p_b.type != BOOL) - _RETURN_FAIL; - - if (p_a._data._bool == p_b._data._bool) - _RETURN(false); - - if (!p_a._data._bool && p_b._data._bool) - _RETURN(false); - - _RETURN(true); - } - - CASE_TYPE(math, OP_GREATER, OBJECT) { - if (p_b.type != OBJECT) - _RETURN_FAIL; - _RETURN((p_a._get_obj().obj > p_b._get_obj().obj)); - } - - CASE_TYPE(math, OP_GREATER, ARRAY) { - if (p_b.type != ARRAY) - _RETURN_FAIL; - - const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem); - const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem); - - int l = arr_a->size(); - if (arr_b->size() > l) - _RETURN(false); - for (int i = 0; i < l; i++) { - if (((*arr_a)[i] < (*arr_b)[i])) { - _RETURN(false); - } - } - - _RETURN(true); - } - - DEFAULT_OP_NUM(math, OP_GREATER, INT, >, _int); - DEFAULT_OP_NUM(math, OP_GREATER, FLOAT, >, _float); - DEFAULT_OP_STR_REV(math, OP_GREATER, STRING, <, String); - DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR2, <, Vector2); - DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR2I, <, Vector2i); - DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR3, <, Vector3); - DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR3I, <, Vector3i); - DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, _RID, <, RID); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_INT32_ARRAY, int32_t); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_INT64_ARRAY, int64_t); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_FLOAT32_ARRAY, float); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_FLOAT64_ARRAY, double); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_VECTOR2_ARRAY, Vector3); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_GT(math, OP_GREATER, PACKED_COLOR_ARRAY, Color); - - CASE_TYPE(math, OP_GREATER, NIL) - CASE_TYPE(math, OP_GREATER, RECT2) - CASE_TYPE(math, OP_GREATER, RECT2I) - CASE_TYPE(math, OP_GREATER, TRANSFORM2D) - CASE_TYPE(math, OP_GREATER, PLANE) - CASE_TYPE(math, OP_GREATER, QUAT) - CASE_TYPE(math, OP_GREATER, AABB) - CASE_TYPE(math, OP_GREATER, BASIS) - CASE_TYPE(math, OP_GREATER, TRANSFORM) - CASE_TYPE(math, OP_GREATER, COLOR) - CASE_TYPE(math, OP_GREATER, STRING_NAME) - CASE_TYPE(math, OP_GREATER, NODE_PATH) - CASE_TYPE(math, OP_GREATER, DICTIONARY) - CASE_TYPE(math, OP_GREATER, CALLABLE) - CASE_TYPE(math, OP_GREATER, SIGNAL) - - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_GREATER_EQUAL, p_a.type) { - CASE_TYPE(math, OP_GREATER_EQUAL, OBJECT) { - if (p_b.type != OBJECT) - _RETURN_FAIL; - _RETURN((p_a._get_obj().obj >= p_b._get_obj().obj)); - } - - DEFAULT_OP_NUM(math, OP_GREATER_EQUAL, INT, >=, _int); - DEFAULT_OP_NUM(math, OP_GREATER_EQUAL, FLOAT, >=, _float); - DEFAULT_OP_STR_REV(math, OP_GREATER_EQUAL, STRING, <=, String); - DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR2, <=, Vector2); - DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR2I, <=, Vector2i); - DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR3, <=, Vector3); - DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR3I, <=, Vector3i); - DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, _RID, <=, RID); - - CASE_TYPE(math, OP_GREATER_EQUAL, NIL) - CASE_TYPE(math, OP_GREATER_EQUAL, BOOL) - CASE_TYPE(math, OP_GREATER_EQUAL, RECT2) - CASE_TYPE(math, OP_GREATER_EQUAL, RECT2I) - CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM2D) - CASE_TYPE(math, OP_GREATER_EQUAL, PLANE) - CASE_TYPE(math, OP_GREATER_EQUAL, QUAT) - CASE_TYPE(math, OP_GREATER_EQUAL, AABB) - CASE_TYPE(math, OP_GREATER_EQUAL, BASIS) - CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM) - CASE_TYPE(math, OP_GREATER_EQUAL, COLOR) - CASE_TYPE(math, OP_GREATER_EQUAL, STRING_NAME) - CASE_TYPE(math, OP_GREATER_EQUAL, NODE_PATH) - CASE_TYPE(math, OP_GREATER_EQUAL, CALLABLE) - CASE_TYPE(math, OP_GREATER_EQUAL, SIGNAL) - - CASE_TYPE(math, OP_GREATER_EQUAL, DICTIONARY) - CASE_TYPE(math, OP_GREATER_EQUAL, ARRAY) - CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_BYTE_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_INT32_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_INT64_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_FLOAT32_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_FLOAT64_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_STRING_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_VECTOR2_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_VECTOR3_ARRAY); - CASE_TYPE(math, OP_GREATER_EQUAL, PACKED_COLOR_ARRAY); - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_ADD, p_a.type) { - CASE_TYPE(math, OP_ADD, ARRAY) { - if (p_a.type != p_b.type) - _RETURN_FAIL; - - const Array &array_a = *reinterpret_cast<const Array *>(p_a._data._mem); - const Array &array_b = *reinterpret_cast<const Array *>(p_b._data._mem); - Array sum; - int asize = array_a.size(); - int bsize = array_b.size(); - sum.resize(asize + bsize); - for (int i = 0; i < asize; i++) { - sum[i] = array_a[i]; - } - for (int i = 0; i < bsize; i++) { - sum[i + asize] = array_b[i]; - } - _RETURN(sum); - } - - DEFAULT_OP_NUM(math, OP_ADD, INT, +, _int); - DEFAULT_OP_NUM(math, OP_ADD, FLOAT, +, _float); - DEFAULT_OP_STR(math, OP_ADD, STRING, +, String); - DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR2, +, Vector2); - DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR2I, +, Vector2i); - DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR3, +, Vector3); - DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR3I, +, Vector3i); - DEFAULT_OP_LOCALMEM(math, OP_ADD, QUAT, +, Quat); - DEFAULT_OP_LOCALMEM(math, OP_ADD, COLOR, +, Color); - - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_BYTE_ARRAY, uint8_t); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_INT32_ARRAY, int32_t); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_INT64_ARRAY, int64_t); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_FLOAT32_ARRAY, float); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_FLOAT64_ARRAY, double); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_STRING_ARRAY, String); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_VECTOR2_ARRAY, Vector2); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_VECTOR3_ARRAY, Vector3); - DEFAULT_OP_ARRAY_ADD(math, OP_ADD, PACKED_COLOR_ARRAY, Color); - - CASE_TYPE(math, OP_ADD, NIL) - CASE_TYPE(math, OP_ADD, BOOL) - CASE_TYPE(math, OP_ADD, RECT2) - CASE_TYPE(math, OP_ADD, RECT2I) - CASE_TYPE(math, OP_ADD, TRANSFORM2D) - CASE_TYPE(math, OP_ADD, PLANE) - CASE_TYPE(math, OP_ADD, AABB) - CASE_TYPE(math, OP_ADD, BASIS) - CASE_TYPE(math, OP_ADD, TRANSFORM) - CASE_TYPE(math, OP_ADD, STRING_NAME) - CASE_TYPE(math, OP_ADD, NODE_PATH) - CASE_TYPE(math, OP_ADD, _RID) - CASE_TYPE(math, OP_ADD, OBJECT) - CASE_TYPE(math, OP_ADD, CALLABLE) - CASE_TYPE(math, OP_ADD, SIGNAL) - - CASE_TYPE(math, OP_ADD, DICTIONARY) - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_SUBTRACT, p_a.type) { - DEFAULT_OP_NUM(math, OP_SUBTRACT, INT, -, _int); - DEFAULT_OP_NUM(math, OP_SUBTRACT, FLOAT, -, _float); - DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR2, -, Vector2); - DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR2I, -, Vector2i); - DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR3, -, Vector3); - DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR3I, -, Vector3i); - DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, QUAT, -, Quat); - DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, COLOR, -, Color); - - CASE_TYPE(math, OP_SUBTRACT, NIL) - CASE_TYPE(math, OP_SUBTRACT, BOOL) - CASE_TYPE(math, OP_SUBTRACT, STRING) - CASE_TYPE(math, OP_SUBTRACT, RECT2) - CASE_TYPE(math, OP_SUBTRACT, RECT2I) - CASE_TYPE(math, OP_SUBTRACT, TRANSFORM2D) - CASE_TYPE(math, OP_SUBTRACT, PLANE) - CASE_TYPE(math, OP_SUBTRACT, AABB) - CASE_TYPE(math, OP_SUBTRACT, BASIS) - CASE_TYPE(math, OP_SUBTRACT, TRANSFORM) - CASE_TYPE(math, OP_SUBTRACT, STRING_NAME) - CASE_TYPE(math, OP_SUBTRACT, NODE_PATH) - CASE_TYPE(math, OP_SUBTRACT, _RID) - CASE_TYPE(math, OP_SUBTRACT, OBJECT) - CASE_TYPE(math, OP_SUBTRACT, CALLABLE) - CASE_TYPE(math, OP_SUBTRACT, SIGNAL) - - CASE_TYPE(math, OP_SUBTRACT, DICTIONARY) - CASE_TYPE(math, OP_SUBTRACT, ARRAY) - CASE_TYPE(math, OP_SUBTRACT, PACKED_BYTE_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, PACKED_INT32_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, PACKED_INT64_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, PACKED_FLOAT32_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, PACKED_FLOAT64_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, PACKED_STRING_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, PACKED_VECTOR2_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, PACKED_VECTOR3_ARRAY); - CASE_TYPE(math, OP_SUBTRACT, PACKED_COLOR_ARRAY); - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_MULTIPLY, p_a.type) { - CASE_TYPE(math, OP_MULTIPLY, TRANSFORM2D) { - switch (p_b.type) { - case TRANSFORM2D: { - _RETURN(*p_a._data._transform2d * *p_b._data._transform2d); - } - case VECTOR2: { - _RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem)); - } - default: - _RETURN_FAIL; - } - } - - CASE_TYPE(math, OP_MULTIPLY, QUAT) { - switch (p_b.type) { - case VECTOR3: { - _RETURN(reinterpret_cast<const Quat *>(p_a._data._mem)->xform(*(const Vector3 *)p_b._data._mem)); - } - case QUAT: { - _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * *reinterpret_cast<const Quat *>(p_b._data._mem)); - } - case FLOAT: { - _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._float); - } - case INT: { - _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._int); - } - default: - _RETURN_FAIL; - } - } - - CASE_TYPE(math, OP_MULTIPLY, BASIS) { - switch (p_b.type) { - case VECTOR3: { - _RETURN(p_a._data._basis->xform(*(const Vector3 *)p_b._data._mem)); - } - case BASIS: { - _RETURN(*p_a._data._basis * *p_b._data._basis); - } - default: - _RETURN_FAIL; - } - } - - CASE_TYPE(math, OP_MULTIPLY, TRANSFORM) { - switch (p_b.type) { - case VECTOR3: { - _RETURN(p_a._data._transform->xform(*(const Vector3 *)p_b._data._mem)); - } - case TRANSFORM: { - _RETURN(*p_a._data._transform * *p_b._data._transform); - } - default: - _RETURN_FAIL; - } - } - - CASE_TYPE(math, OP_MULTIPLY, INT) { - if (p_b.type == INT) { - _RETURN(p_a._data._int * p_b._data._int); - } - if (p_b.type == FLOAT) { - _RETURN(p_a._data._int * p_b._data._float); - } - if (p_b.type == VECTOR2) { - _RETURN(p_a._data._int * *reinterpret_cast<const Vector2 *>(p_b._data._mem)); - } - if (p_b.type == VECTOR3) { - _RETURN(p_a._data._int * *reinterpret_cast<const Vector3 *>(p_b._data._mem)); - } - if (p_b.type == VECTOR2I) { - _RETURN(p_a._data._int * *reinterpret_cast<const Vector2i *>(p_b._data._mem)); - } - if (p_b.type == VECTOR3I) { - _RETURN(p_a._data._int * *reinterpret_cast<const Vector3i *>(p_b._data._mem)); - } - if (p_b.type == QUAT) { - _RETURN(p_a._data._int * *reinterpret_cast<const Quat *>(p_b._data._mem)); - } - if (p_b.type == COLOR) { - _RETURN(p_a._data._int * *reinterpret_cast<const Color *>(p_b._data._mem)); - } - - _RETURN_FAIL - } - - CASE_TYPE(math, OP_MULTIPLY, FLOAT) { - if (p_b.type == INT) { - _RETURN(p_a._data._float * p_b._data._int); - } - if (p_b.type == FLOAT) { - _RETURN(p_a._data._float * p_b._data._float); - } - if (p_b.type == VECTOR2) { - _RETURN(p_a._data._float * *reinterpret_cast<const Vector2 *>(p_b._data._mem)); - } - if (p_b.type == VECTOR3) { - _RETURN(p_a._data._float * *reinterpret_cast<const Vector3 *>(p_b._data._mem)); - } - if (p_b.type == VECTOR2I) { - _RETURN(p_a._data._float * *reinterpret_cast<const Vector2i *>(p_b._data._mem)); - } - if (p_b.type == VECTOR3I) { - _RETURN(p_a._data._float * *reinterpret_cast<const Vector3i *>(p_b._data._mem)); - } - if (p_b.type == QUAT) { - _RETURN(p_a._data._float * *reinterpret_cast<const Quat *>(p_b._data._mem)); - } - if (p_b.type == COLOR) { - _RETURN(p_a._data._float * *reinterpret_cast<const Color *>(p_b._data._mem)); - } - - _RETURN_FAIL - } - - DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR2, *, Vector2); - DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR2I, *, Vector2i); - DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR3, *, Vector3); - DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR3I, *, Vector3i); - DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, COLOR, *, Color); - - CASE_TYPE(math, OP_MULTIPLY, NIL) - CASE_TYPE(math, OP_MULTIPLY, BOOL) - CASE_TYPE(math, OP_MULTIPLY, STRING) - CASE_TYPE(math, OP_MULTIPLY, RECT2) - CASE_TYPE(math, OP_MULTIPLY, RECT2I) - CASE_TYPE(math, OP_MULTIPLY, PLANE) - CASE_TYPE(math, OP_MULTIPLY, AABB) - CASE_TYPE(math, OP_MULTIPLY, STRING_NAME) - CASE_TYPE(math, OP_MULTIPLY, NODE_PATH) - CASE_TYPE(math, OP_MULTIPLY, _RID) - CASE_TYPE(math, OP_MULTIPLY, OBJECT) - CASE_TYPE(math, OP_MULTIPLY, CALLABLE) - CASE_TYPE(math, OP_MULTIPLY, SIGNAL) - - CASE_TYPE(math, OP_MULTIPLY, DICTIONARY) - CASE_TYPE(math, OP_MULTIPLY, ARRAY) - CASE_TYPE(math, OP_MULTIPLY, PACKED_BYTE_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, PACKED_INT32_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, PACKED_INT64_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, PACKED_FLOAT32_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, PACKED_FLOAT64_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, PACKED_STRING_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, PACKED_VECTOR2_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, PACKED_VECTOR3_ARRAY); - CASE_TYPE(math, OP_MULTIPLY, PACKED_COLOR_ARRAY); - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_DIVIDE, p_a.type) { - CASE_TYPE(math, OP_DIVIDE, QUAT) { - if (p_b.type != FLOAT) - _RETURN_FAIL; -#ifdef DEBUG_ENABLED - if (p_b._data._float == 0) { - r_valid = false; - _RETURN("Division By Zero"); - } -#endif - _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) / p_b._data._float); - } - - DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, INT, _int); - DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, FLOAT, _float); - DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR2, /, Vector2); - DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR2I, /, Vector2i); - DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR3, /, Vector3); - DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR3I, /, Vector3i); - DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, COLOR, /, Color); - - CASE_TYPE(math, OP_DIVIDE, NIL) - CASE_TYPE(math, OP_DIVIDE, BOOL) - CASE_TYPE(math, OP_DIVIDE, STRING) - CASE_TYPE(math, OP_DIVIDE, RECT2) - CASE_TYPE(math, OP_DIVIDE, RECT2I) - CASE_TYPE(math, OP_DIVIDE, TRANSFORM2D) - CASE_TYPE(math, OP_DIVIDE, PLANE) - CASE_TYPE(math, OP_DIVIDE, AABB) - CASE_TYPE(math, OP_DIVIDE, BASIS) - CASE_TYPE(math, OP_DIVIDE, TRANSFORM) - CASE_TYPE(math, OP_DIVIDE, STRING_NAME) - CASE_TYPE(math, OP_DIVIDE, NODE_PATH) - CASE_TYPE(math, OP_DIVIDE, _RID) - CASE_TYPE(math, OP_DIVIDE, OBJECT) - CASE_TYPE(math, OP_DIVIDE, CALLABLE) - CASE_TYPE(math, OP_DIVIDE, SIGNAL) - - CASE_TYPE(math, OP_DIVIDE, DICTIONARY) - CASE_TYPE(math, OP_DIVIDE, ARRAY) - CASE_TYPE(math, OP_DIVIDE, PACKED_BYTE_ARRAY); - CASE_TYPE(math, OP_DIVIDE, PACKED_INT32_ARRAY); - CASE_TYPE(math, OP_DIVIDE, PACKED_INT64_ARRAY); - CASE_TYPE(math, OP_DIVIDE, PACKED_FLOAT32_ARRAY); - CASE_TYPE(math, OP_DIVIDE, PACKED_FLOAT64_ARRAY); - CASE_TYPE(math, OP_DIVIDE, PACKED_STRING_ARRAY); - CASE_TYPE(math, OP_DIVIDE, PACKED_VECTOR2_ARRAY); - CASE_TYPE(math, OP_DIVIDE, PACKED_VECTOR3_ARRAY); - CASE_TYPE(math, OP_DIVIDE, PACKED_COLOR_ARRAY); - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_POSITIVE, p_a.type) { - DEFAULT_OP_NUM_POS(math, OP_POSITIVE, INT, _int); - DEFAULT_OP_NUM_POS(math, OP_POSITIVE, FLOAT, _float); - DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR3, Vector3); - DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR3I, Vector3i); - DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, PLANE, Plane); - DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, QUAT, Quat); - DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR2, Vector2); - DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR2I, Vector2i); - - CASE_TYPE(math, OP_POSITIVE, NIL) - CASE_TYPE(math, OP_POSITIVE, BOOL) - CASE_TYPE(math, OP_POSITIVE, STRING) - CASE_TYPE(math, OP_POSITIVE, RECT2) - CASE_TYPE(math, OP_POSITIVE, RECT2I) - CASE_TYPE(math, OP_POSITIVE, TRANSFORM2D) - CASE_TYPE(math, OP_POSITIVE, AABB) - CASE_TYPE(math, OP_POSITIVE, BASIS) - CASE_TYPE(math, OP_POSITIVE, TRANSFORM) - CASE_TYPE(math, OP_POSITIVE, COLOR) - CASE_TYPE(math, OP_POSITIVE, STRING_NAME) - CASE_TYPE(math, OP_POSITIVE, NODE_PATH) - CASE_TYPE(math, OP_POSITIVE, _RID) - CASE_TYPE(math, OP_POSITIVE, OBJECT) - CASE_TYPE(math, OP_POSITIVE, CALLABLE) - CASE_TYPE(math, OP_POSITIVE, SIGNAL) - - CASE_TYPE(math, OP_POSITIVE, DICTIONARY) - CASE_TYPE(math, OP_POSITIVE, ARRAY) - CASE_TYPE(math, OP_POSITIVE, PACKED_BYTE_ARRAY) - CASE_TYPE(math, OP_POSITIVE, PACKED_INT32_ARRAY) - CASE_TYPE(math, OP_POSITIVE, PACKED_INT64_ARRAY) - CASE_TYPE(math, OP_POSITIVE, PACKED_FLOAT32_ARRAY) - CASE_TYPE(math, OP_POSITIVE, PACKED_FLOAT64_ARRAY) - CASE_TYPE(math, OP_POSITIVE, PACKED_STRING_ARRAY) - CASE_TYPE(math, OP_POSITIVE, PACKED_VECTOR2_ARRAY) - CASE_TYPE(math, OP_POSITIVE, PACKED_VECTOR3_ARRAY) - CASE_TYPE(math, OP_POSITIVE, PACKED_COLOR_ARRAY) - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_NEGATE, p_a.type) { - DEFAULT_OP_NUM_NEG(math, OP_NEGATE, INT, _int); - DEFAULT_OP_NUM_NEG(math, OP_NEGATE, FLOAT, _float); - - DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR2, Vector2); - DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR2I, Vector2i); - DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR3, Vector3); - DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR3I, Vector3i); - DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, PLANE, Plane); - DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, QUAT, Quat); - DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, COLOR, Color); - - CASE_TYPE(math, OP_NEGATE, NIL) - CASE_TYPE(math, OP_NEGATE, BOOL) - CASE_TYPE(math, OP_NEGATE, STRING) - CASE_TYPE(math, OP_NEGATE, RECT2) - CASE_TYPE(math, OP_NEGATE, RECT2I) - CASE_TYPE(math, OP_NEGATE, TRANSFORM2D) - CASE_TYPE(math, OP_NEGATE, AABB) - CASE_TYPE(math, OP_NEGATE, BASIS) - CASE_TYPE(math, OP_NEGATE, TRANSFORM) - CASE_TYPE(math, OP_NEGATE, STRING_NAME) - CASE_TYPE(math, OP_NEGATE, NODE_PATH) - CASE_TYPE(math, OP_NEGATE, _RID) - CASE_TYPE(math, OP_NEGATE, OBJECT) - CASE_TYPE(math, OP_NEGATE, CALLABLE) - CASE_TYPE(math, OP_NEGATE, SIGNAL) - - CASE_TYPE(math, OP_NEGATE, DICTIONARY) - CASE_TYPE(math, OP_NEGATE, ARRAY) - CASE_TYPE(math, OP_NEGATE, PACKED_BYTE_ARRAY) - CASE_TYPE(math, OP_NEGATE, PACKED_INT32_ARRAY) - CASE_TYPE(math, OP_NEGATE, PACKED_INT64_ARRAY) - CASE_TYPE(math, OP_NEGATE, PACKED_FLOAT32_ARRAY) - CASE_TYPE(math, OP_NEGATE, PACKED_FLOAT64_ARRAY) - CASE_TYPE(math, OP_NEGATE, PACKED_STRING_ARRAY) - CASE_TYPE(math, OP_NEGATE, PACKED_VECTOR2_ARRAY) - CASE_TYPE(math, OP_NEGATE, PACKED_VECTOR3_ARRAY) - CASE_TYPE(math, OP_NEGATE, PACKED_COLOR_ARRAY) - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_MODULE, p_a.type) { - CASE_TYPE(math, OP_MODULE, INT) { - if (p_b.type != INT) - _RETURN_FAIL; -#ifdef DEBUG_ENABLED - if (p_b._data._int == 0) { - r_valid = false; - _RETURN("Division By Zero"); - } -#endif - _RETURN(p_a._data._int % p_b._data._int); - } - - CASE_TYPE(math, OP_MODULE, STRING) { - const String *format = reinterpret_cast<const String *>(p_a._data._mem); - - String result; - bool error; - if (p_b.type == ARRAY) { - // e.g. "frog %s %d" % ["fish", 12] - const Array *args = reinterpret_cast<const Array *>(p_b._data._mem); - result = format->sprintf(*args, &error); - } else { - // e.g. "frog %d" % 12 - Array args; - args.push_back(p_b); - result = format->sprintf(args, &error); - } - r_valid = !error; - _RETURN(result); - } - - CASE_TYPE(math, OP_MODULE, NIL) - CASE_TYPE(math, OP_MODULE, BOOL) - CASE_TYPE(math, OP_MODULE, FLOAT) - CASE_TYPE(math, OP_MODULE, VECTOR2) - CASE_TYPE(math, OP_MODULE, VECTOR2I) - CASE_TYPE(math, OP_MODULE, RECT2) - CASE_TYPE(math, OP_MODULE, RECT2I) - CASE_TYPE(math, OP_MODULE, VECTOR3) - CASE_TYPE(math, OP_MODULE, VECTOR3I) - CASE_TYPE(math, OP_MODULE, TRANSFORM2D) - CASE_TYPE(math, OP_MODULE, PLANE) - CASE_TYPE(math, OP_MODULE, QUAT) - CASE_TYPE(math, OP_MODULE, AABB) - CASE_TYPE(math, OP_MODULE, BASIS) - CASE_TYPE(math, OP_MODULE, TRANSFORM) - CASE_TYPE(math, OP_MODULE, COLOR) - CASE_TYPE(math, OP_MODULE, STRING_NAME) - CASE_TYPE(math, OP_MODULE, NODE_PATH) - CASE_TYPE(math, OP_MODULE, _RID) - CASE_TYPE(math, OP_MODULE, OBJECT) - CASE_TYPE(math, OP_MODULE, CALLABLE) - CASE_TYPE(math, OP_MODULE, SIGNAL) - - CASE_TYPE(math, OP_MODULE, DICTIONARY) - CASE_TYPE(math, OP_MODULE, ARRAY) - CASE_TYPE(math, OP_MODULE, PACKED_BYTE_ARRAY) - CASE_TYPE(math, OP_MODULE, PACKED_INT32_ARRAY) - CASE_TYPE(math, OP_MODULE, PACKED_INT64_ARRAY) - CASE_TYPE(math, OP_MODULE, PACKED_FLOAT32_ARRAY) - CASE_TYPE(math, OP_MODULE, PACKED_FLOAT64_ARRAY) - CASE_TYPE(math, OP_MODULE, PACKED_STRING_ARRAY) - CASE_TYPE(math, OP_MODULE, PACKED_VECTOR2_ARRAY) - CASE_TYPE(math, OP_MODULE, PACKED_VECTOR3_ARRAY) - CASE_TYPE(math, OP_MODULE, PACKED_COLOR_ARRAY) - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_STRING_CONCAT, p_a.type) { - CASE_TYPE_ALL(math, OP_STRING_CONCAT) - - _RETURN(p_a.operator String() + p_b.operator String()); - } - - SWITCH_OP(math, OP_SHIFT_LEFT, p_a.type) { - CASE_TYPE(math, OP_SHIFT_LEFT, INT) { - if (p_b.type != INT) - _RETURN_FAIL; - if (p_b._data._int < 0 || p_b._data._int >= 64) - _RETURN_FAIL; - _RETURN(p_a._data._int << p_b._data._int); - } - - CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_LEFT) - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_SHIFT_RIGHT, p_a.type) { - CASE_TYPE(math, OP_SHIFT_RIGHT, INT) { - if (p_b.type != INT) - _RETURN_FAIL; - if (p_b._data._int < 0 || p_b._data._int >= 64) - _RETURN_FAIL; - _RETURN(p_a._data._int >> p_b._data._int); - } - - CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_RIGHT) - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_BIT_AND, p_a.type) { - CASE_TYPE(math, OP_BIT_AND, INT) { - if (p_b.type != INT) - _RETURN_FAIL; - _RETURN(p_a._data._int & p_b._data._int); - } - - CASE_TYPE_ALL_BUT_INT(math, OP_BIT_AND) - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_BIT_OR, p_a.type) { - CASE_TYPE(math, OP_BIT_OR, INT) { - if (p_b.type != INT) - _RETURN_FAIL; - _RETURN(p_a._data._int | p_b._data._int); - } - - CASE_TYPE_ALL_BUT_INT(math, OP_BIT_OR) - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_BIT_XOR, p_a.type) { - CASE_TYPE(math, OP_BIT_XOR, INT) { - if (p_b.type != INT) - _RETURN_FAIL; - _RETURN(p_a._data._int ^ p_b._data._int); - } - - CASE_TYPE_ALL_BUT_INT(math, OP_BIT_XOR) - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_BIT_NEGATE, p_a.type) { - CASE_TYPE(math, OP_BIT_NEGATE, INT) { - _RETURN(~p_a._data._int); - } - - CASE_TYPE_ALL_BUT_INT(math, OP_BIT_NEGATE) - _RETURN_FAIL; - } - - SWITCH_OP(math, OP_AND, p_a.type) { - CASE_TYPE_ALL(math, OP_AND) { - bool l = p_a.booleanize(); - bool r = p_b.booleanize(); - - _RETURN(l && r); - } - } - - SWITCH_OP(math, OP_OR, p_a.type) { - CASE_TYPE_ALL(math, OP_OR) { - bool l = p_a.booleanize(); - bool r = p_b.booleanize(); - - _RETURN(l || r); - } - } - - SWITCH_OP(math, OP_XOR, p_a.type) { - CASE_TYPE_ALL(math, OP_XOR) { - bool l = p_a.booleanize(); - bool r = p_b.booleanize(); - - _RETURN((l || r) && !(l && r)); - } - } - - SWITCH_OP(math, OP_NOT, p_a.type) { - CASE_TYPE_ALL(math, OP_NOT) { - bool l = p_a.booleanize(); - _RETURN(!l); - } - } - - SWITCH_OP(math, OP_IN, p_a.type) { - CASE_TYPE_ALL(math, OP_IN) - _RETURN(p_b.in(p_a, &r_valid)); - } - } -} - -void Variant::set_named(const StringName &p_index, const Variant &p_value, bool *r_valid) { - bool valid = false; - switch (type) { - case VECTOR2: { - if (p_value.type == Variant::INT) { - Vector2 *v = reinterpret_cast<Vector2 *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._int; - valid = true; - } - } else if (p_value.type == Variant::FLOAT) { - Vector2 *v = reinterpret_cast<Vector2 *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._float; - valid = true; - } - } - - } break; - case VECTOR2I: { - if (p_value.type == Variant::INT) { - Vector2i *v = reinterpret_cast<Vector2i *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._int; - valid = true; - } - } else if (p_value.type == Variant::FLOAT) { - Vector2i *v = reinterpret_cast<Vector2i *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._float; - valid = true; - } - } - - } break; - case RECT2: { - if (p_value.type == Variant::VECTOR2) { - Rect2 *v = reinterpret_cast<Rect2 *>(_data._mem); - //scalar name - if (p_index == CoreStringNames::singleton->position) { - v->position = *reinterpret_cast<const Vector2 *>(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->size) { - v->size = *reinterpret_cast<const Vector2 *>(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->end) { - v->size = *reinterpret_cast<const Vector2 *>(p_value._data._mem) - v->position; - valid = true; - } - } - } break; - case RECT2I: { - if (p_value.type == Variant::VECTOR2I) { - Rect2i *v = reinterpret_cast<Rect2i *>(_data._mem); - //scalar name - if (p_index == CoreStringNames::singleton->position) { - v->position = *reinterpret_cast<const Vector2i *>(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->size) { - v->size = *reinterpret_cast<const Vector2i *>(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->end) { - v->size = *reinterpret_cast<const Vector2i *>(p_value._data._mem) - v->position; - valid = true; - } - } - } break; - case TRANSFORM2D: { - if (p_value.type == Variant::VECTOR2) { - Transform2D *v = _data._transform2d; - if (p_index == CoreStringNames::singleton->x) { - v->elements[0] = *reinterpret_cast<const Vector2 *>(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->elements[1] = *reinterpret_cast<const Vector2 *>(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->origin) { - v->elements[2] = *reinterpret_cast<const Vector2 *>(p_value._data._mem); - valid = true; - } - } - - } break; - case VECTOR3: { - if (p_value.type == Variant::INT) { - Vector3 *v = reinterpret_cast<Vector3 *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->z = p_value._data._int; - valid = true; - } - } else if (p_value.type == Variant::FLOAT) { - Vector3 *v = reinterpret_cast<Vector3 *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->z = p_value._data._float; - valid = true; - } - } - - } break; - case VECTOR3I: { - if (p_value.type == Variant::INT) { - Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->z = p_value._data._int; - valid = true; - } - } else if (p_value.type == Variant::FLOAT) { - Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->z = p_value._data._float; - valid = true; - } - } - - } break; - case PLANE: { - if (p_value.type == Variant::INT) { - Plane *v = reinterpret_cast<Plane *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->normal.x = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->normal.y = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->normal.z = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->d) { - v->d = p_value._data._int; - valid = true; - } - } else if (p_value.type == Variant::FLOAT) { - Plane *v = reinterpret_cast<Plane *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->normal.x = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->normal.y = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->normal.z = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->d) { - v->d = p_value._data._float; - valid = true; - } - - } else if (p_value.type == Variant::VECTOR3) { - Plane *v = reinterpret_cast<Plane *>(_data._mem); - if (p_index == CoreStringNames::singleton->normal) { - v->normal = *reinterpret_cast<const Vector3 *>(p_value._data._mem); - valid = true; - } - } - - } break; - case QUAT: { - if (p_value.type == Variant::INT) { - Quat *v = reinterpret_cast<Quat *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->z = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->w) { - v->w = p_value._data._int; - valid = true; - } - } else if (p_value.type == Variant::FLOAT) { - Quat *v = reinterpret_cast<Quat *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - v->x = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->y = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->z = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->w) { - v->w = p_value._data._float; - valid = true; - } - } - - } break; - case AABB: { - if (p_value.type == Variant::VECTOR3) { - ::AABB *v = _data._aabb; - //scalar name - if (p_index == CoreStringNames::singleton->position) { - v->position = *reinterpret_cast<const Vector3 *>(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->size) { - v->size = *reinterpret_cast<const Vector3 *>(p_value._data._mem); - valid = true; - } else if (p_index == CoreStringNames::singleton->end) { - v->size = *reinterpret_cast<const Vector3 *>(p_value._data._mem) - v->position; - valid = true; - } - } - } break; - case BASIS: { - if (p_value.type == Variant::VECTOR3) { - Basis *v = _data._basis; - //scalar name - if (p_index == CoreStringNames::singleton->x) { - v->set_axis(0, *reinterpret_cast<const Vector3 *>(p_value._data._mem)); - valid = true; - } else if (p_index == CoreStringNames::singleton->y) { - v->set_axis(1, *reinterpret_cast<const Vector3 *>(p_value._data._mem)); - valid = true; - } else if (p_index == CoreStringNames::singleton->z) { - v->set_axis(2, *reinterpret_cast<const Vector3 *>(p_value._data._mem)); - valid = true; - } - } - } break; - case TRANSFORM: { - if (p_value.type == Variant::BASIS && p_index == CoreStringNames::singleton->basis) { - _data._transform->basis = *p_value._data._basis; - valid = true; - } else if (p_value.type == Variant::VECTOR3 && p_index == CoreStringNames::singleton->origin) { - _data._transform->origin = *reinterpret_cast<const Vector3 *>(p_value._data._mem); - valid = true; - } - - } break; - case COLOR: { - if (p_value.type == Variant::INT) { - Color *v = reinterpret_cast<Color *>(_data._mem); - if (p_index == CoreStringNames::singleton->r) { - v->r = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->g) { - v->g = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->b) { - v->b = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->a) { - v->a = p_value._data._int; - valid = true; - } else if (p_index == CoreStringNames::singleton->r8) { - v->r = p_value._data._int / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->g8) { - v->g = p_value._data._int / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->b8) { - v->b = p_value._data._int / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->a8) { - v->a = p_value._data._int / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->h) { - v->set_hsv(p_value._data._int, v->get_s(), v->get_v(), v->a); - valid = true; - } else if (p_index == CoreStringNames::singleton->s) { - v->set_hsv(v->get_h(), p_value._data._int, v->get_v(), v->a); - valid = true; - } else if (p_index == CoreStringNames::singleton->v) { - v->set_hsv(v->get_h(), v->get_v(), p_value._data._int, v->a); - valid = true; - } - } else if (p_value.type == Variant::FLOAT) { - Color *v = reinterpret_cast<Color *>(_data._mem); - if (p_index == CoreStringNames::singleton->r) { - v->r = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->g) { - v->g = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->b) { - v->b = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->a) { - v->a = p_value._data._float; - valid = true; - } else if (p_index == CoreStringNames::singleton->r8) { - v->r = p_value._data._float / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->g8) { - v->g = p_value._data._float / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->b8) { - v->b = p_value._data._float / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->a8) { - v->a = p_value._data._float / 255.0; - valid = true; - } else if (p_index == CoreStringNames::singleton->h) { - v->set_hsv(p_value._data._float, v->get_s(), v->get_v(), v->a); - valid = true; - } else if (p_index == CoreStringNames::singleton->s) { - v->set_hsv(v->get_h(), p_value._data._float, v->get_v(), v->a); - valid = true; - } else if (p_index == CoreStringNames::singleton->v) { - v->set_hsv(v->get_h(), v->get_s(), p_value._data._float, v->a); - valid = true; - } - } - } break; - case OBJECT: { -#ifdef DEBUG_ENABLED - if (!_get_obj().obj) { - break; - } else if (EngineDebugger::is_active() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - break; - } - -#endif - _get_obj().obj->set(p_index, p_value, &valid); - - } break; - default: { - set(p_index.operator String(), p_value, &valid); - } break; - } - - if (r_valid) { - *r_valid = valid; - } -} - -Variant Variant::get_named(const StringName &p_index, bool *r_valid) const { - if (r_valid) { - *r_valid = true; - } - - switch (type) { - case VECTOR2: { - const Vector2 *v = reinterpret_cast<const Vector2 *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - return v->x; - } else if (p_index == CoreStringNames::singleton->y) { - return v->y; - } - - } break; - case VECTOR2I: { - const Vector2i *v = reinterpret_cast<const Vector2i *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - return v->x; - } else if (p_index == CoreStringNames::singleton->y) { - return v->y; - } - - } break; - case RECT2: { - const Rect2 *v = reinterpret_cast<const Rect2 *>(_data._mem); - //scalar name - if (p_index == CoreStringNames::singleton->position) { - return v->position; - } else if (p_index == CoreStringNames::singleton->size) { - return v->size; - } else if (p_index == CoreStringNames::singleton->end) { - return v->size + v->position; - } - } break; - case RECT2I: { - const Rect2i *v = reinterpret_cast<const Rect2i *>(_data._mem); - //scalar name - if (p_index == CoreStringNames::singleton->position) { - return v->position; - } else if (p_index == CoreStringNames::singleton->size) { - return v->size; - } else if (p_index == CoreStringNames::singleton->end) { - return v->size + v->position; - } - } break; - case TRANSFORM2D: { - const Transform2D *v = _data._transform2d; - if (p_index == CoreStringNames::singleton->x) { - return v->elements[0]; - } else if (p_index == CoreStringNames::singleton->y) { - return v->elements[1]; - } else if (p_index == CoreStringNames::singleton->origin) { - return v->elements[2]; - } - - } break; - case VECTOR3: { - const Vector3 *v = reinterpret_cast<const Vector3 *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - return v->x; - } else if (p_index == CoreStringNames::singleton->y) { - return v->y; - } else if (p_index == CoreStringNames::singleton->z) { - return v->z; - } - - } break; - case VECTOR3I: { - const Vector3i *v = reinterpret_cast<const Vector3i *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - return v->x; - } else if (p_index == CoreStringNames::singleton->y) { - return v->y; - } else if (p_index == CoreStringNames::singleton->z) { - return v->z; - } - - } break; - case PLANE: { - const Plane *v = reinterpret_cast<const Plane *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - return v->normal.x; - } else if (p_index == CoreStringNames::singleton->y) { - return v->normal.y; - } else if (p_index == CoreStringNames::singleton->z) { - return v->normal.z; - } else if (p_index == CoreStringNames::singleton->d) { - return v->d; - } else if (p_index == CoreStringNames::singleton->normal) { - return v->normal; - } - - } break; - case QUAT: { - const Quat *v = reinterpret_cast<const Quat *>(_data._mem); - if (p_index == CoreStringNames::singleton->x) { - return v->x; - } else if (p_index == CoreStringNames::singleton->y) { - return v->y; - } else if (p_index == CoreStringNames::singleton->z) { - return v->z; - } else if (p_index == CoreStringNames::singleton->w) { - return v->w; - } - - } break; - case AABB: { - const ::AABB *v = _data._aabb; - //scalar name - if (p_index == CoreStringNames::singleton->position) { - return v->position; - } else if (p_index == CoreStringNames::singleton->size) { - return v->size; - } else if (p_index == CoreStringNames::singleton->end) { - return v->size + v->position; - } - } break; - case BASIS: { - const Basis *v = _data._basis; - //scalar name - if (p_index == CoreStringNames::singleton->x) { - return v->get_axis(0); - } else if (p_index == CoreStringNames::singleton->y) { - return v->get_axis(1); - } else if (p_index == CoreStringNames::singleton->z) { - return v->get_axis(2); - } - - } break; - case TRANSFORM: { - if (p_index == CoreStringNames::singleton->basis) { - return _data._transform->basis; - } else if (p_index == CoreStringNames::singleton->origin) { - return _data._transform->origin; - } - - } break; - case COLOR: { - const Color *v = reinterpret_cast<const Color *>(_data._mem); - if (p_index == CoreStringNames::singleton->r) { - return v->r; - } else if (p_index == CoreStringNames::singleton->g) { - return v->g; - } else if (p_index == CoreStringNames::singleton->b) { - return v->b; - } else if (p_index == CoreStringNames::singleton->a) { - return v->a; - } else if (p_index == CoreStringNames::singleton->r8) { - return int(Math::round(v->r * 255.0)); - } else if (p_index == CoreStringNames::singleton->g8) { - return int(Math::round(v->g * 255.0)); - } else if (p_index == CoreStringNames::singleton->b8) { - return int(Math::round(v->b * 255.0)); - } else if (p_index == CoreStringNames::singleton->a8) { - return int(Math::round(v->a * 255.0)); - } else if (p_index == CoreStringNames::singleton->h) { - return v->get_h(); - } else if (p_index == CoreStringNames::singleton->s) { - return v->get_s(); - } else if (p_index == CoreStringNames::singleton->v) { - return v->get_v(); - } - } break; - case OBJECT: { -#ifdef DEBUG_ENABLED - if (!_get_obj().obj) { - if (r_valid) { - *r_valid = false; - } - return "Instance base is null."; - } else { - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - if (r_valid) { - *r_valid = false; - } - return "Attempted use of stray pointer object."; - } - } - -#endif - - return _get_obj().obj->get(p_index, r_valid); - - } break; - default: { - return get(p_index.operator String(), r_valid); - } - } - - if (r_valid) { - *r_valid = false; - } - return Variant(); -} - -#define DEFAULT_OP_ARRAY_CMD(m_name, m_type, skip_test, cmd) \ - case m_name: { \ - skip_test; \ - \ - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { \ - int index = p_index; \ - m_type *arr = reinterpret_cast<m_type *>(_data._mem); \ - \ - if (index < 0) \ - index += arr->size(); \ - if (index >= 0 && index < arr->size()) { \ - valid = true; \ - cmd; \ - } \ - } \ - } break; - -#define DEFAULT_OP_DVECTOR_SET(m_name, m_type, skip_cond) \ - case m_name: { \ - if (skip_cond) \ - return; \ - \ - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { \ - int index = p_index; \ - Vector<m_type> *arr = PackedArrayRef<m_type>::get_array_ptr(_data.packed_array); \ - \ - if (index < 0) \ - index += arr->size(); \ - if (index >= 0 && index < arr->size()) { \ - valid = true; \ - arr->set(index, p_value); \ - } \ - } \ - } break; - -#define DEFAULT_OP_DVECTOR_GET(m_name, m_type) \ - case m_name: { \ - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { \ - int index = p_index; \ - const Vector<m_type> *arr = &PackedArrayRef<m_type>::get_array(_data.packed_array); \ - \ - if (index < 0) \ - index += arr->size(); \ - if (index >= 0 && index < arr->size()) { \ - valid = true; \ - return arr->get(index); \ - } \ - } \ - } break; - -void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid) { - static bool _dummy = false; - - bool &valid = r_valid ? *r_valid : _dummy; - valid = false; - - switch (type) { - case NIL: { - return; - } break; - case BOOL: { - return; - } break; - case INT: { - return; - } break; - case FLOAT: { - return; - } break; - case STRING: { - if (p_index.type != Variant::INT && p_index.type != Variant::FLOAT) { - return; - } - - int idx = p_index; - String *str = reinterpret_cast<String *>(_data._mem); - int len = str->length(); - if (idx < 0) { - idx += len; - } - if (idx < 0 || idx >= len) { - return; - } - - String chr; - if (p_value.type == Variant::INT || p_value.type == Variant::FLOAT) { - chr = String::chr(p_value); - } else if (p_value.type == Variant::STRING) { - chr = p_value; - } else { - return; - } - - *str = str->substr(0, idx) + chr + str->substr(idx + 1, len); - valid = true; - return; - - } break; - case VECTOR2: { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - // scalar index - int idx = p_index; - - if (idx < 0) { - idx += 2; - } - if (idx >= 0 && idx < 2) { - Vector2 *v = reinterpret_cast<Vector2 *>(_data._mem); - valid = true; - (*v)[idx] = p_value; - return; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - Vector2 *v = reinterpret_cast<Vector2 *>(_data._mem); - if (*str == "x") { - valid = true; - v->x = p_value; - return; - } else if (*str == "y") { - valid = true; - v->y = p_value; - return; - } - } - - } break; - case VECTOR2I: { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - // scalar index - int idx = p_index; - - if (idx < 0) { - idx += 2; - } - if (idx >= 0 && idx < 2) { - Vector2i *v = reinterpret_cast<Vector2i *>(_data._mem); - valid = true; - (*v)[idx] = p_value; - return; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - Vector2i *v = reinterpret_cast<Vector2i *>(_data._mem); - if (*str == "x") { - valid = true; - v->x = p_value; - return; - } else if (*str == "y") { - valid = true; - v->y = p_value; - return; - } - } - - } break; - case RECT2: { - if (p_value.type != Variant::VECTOR2) { - return; - } - - if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - Rect2 *v = reinterpret_cast<Rect2 *>(_data._mem); - if (*str == "position") { - valid = true; - v->position = p_value; - return; - } else if (*str == "size") { - valid = true; - v->size = p_value; - return; - } else if (*str == "end") { - valid = true; - v->size = Vector2(p_value) - v->position; - return; - } - } - } break; - case RECT2I: { - if (p_value.type != Variant::VECTOR2I) { - return; - } - - if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - Rect2i *v = reinterpret_cast<Rect2i *>(_data._mem); - if (*str == "position") { - valid = true; - v->position = p_value; - return; - } else if (*str == "size") { - valid = true; - v->size = p_value; - return; - } else if (*str == "end") { - valid = true; - v->size = Vector2i(p_value) - v->position; - return; - } - } - } break; - case TRANSFORM2D: { - if (p_value.type != Variant::VECTOR2) { - return; - } - - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - - if (index < 0) { - index += 3; - } - if (index >= 0 && index < 3) { - Transform2D *v = _data._transform2d; - - valid = true; - v->elements[index] = p_value; - return; - } - } else if (p_index.get_type() == Variant::STRING && p_value.get_type() == Variant::VECTOR2) { - //scalar name - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - Transform2D *v = _data._transform2d; - if (*str == "x") { - valid = true; - v->elements[0] = p_value; - return; - } else if (*str == "y") { - valid = true; - v->elements[1] = p_value; - return; - } else if (*str == "origin") { - valid = true; - v->elements[2] = p_value; - return; - } - } - - } break; - case VECTOR3: { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - //scalar index - int idx = p_index; - if (idx < 0) { - idx += 3; - } - if (idx >= 0 && idx < 3) { - Vector3 *v = reinterpret_cast<Vector3 *>(_data._mem); - valid = true; - (*v)[idx] = p_value; - return; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - Vector3 *v = reinterpret_cast<Vector3 *>(_data._mem); - if (*str == "x") { - valid = true; - v->x = p_value; - return; - } else if (*str == "y") { - valid = true; - v->y = p_value; - return; - } else if (*str == "z") { - valid = true; - v->z = p_value; - return; - } - } - - } break; - case VECTOR3I: { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - //scalar index - int idx = p_index; - if (idx < 0) { - idx += 3; - } - if (idx >= 0 && idx < 3) { - Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem); - valid = true; - (*v)[idx] = p_value; - return; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - Vector3i *v = reinterpret_cast<Vector3i *>(_data._mem); - if (*str == "x") { - valid = true; - v->x = p_value; - return; - } else if (*str == "y") { - valid = true; - v->y = p_value; - return; - } else if (*str == "z") { - valid = true; - v->z = p_value; - return; - } - } - - } break; - case PLANE: { - if (p_index.get_type() == Variant::STRING) { - //scalar name - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - Plane *v = reinterpret_cast<Plane *>(_data._mem); - if (*str == "x") { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - valid = true; - v->normal.x = p_value; - return; - } else if (*str == "y") { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - valid = true; - v->normal.y = p_value; - return; - } else if (*str == "z") { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - valid = true; - v->normal.z = p_value; - return; - } else if (*str == "normal") { - if (p_value.type != Variant::VECTOR3) { - return; - } - - valid = true; - v->normal = p_value; - return; - } else if (*str == "d") { - valid = true; - v->d = p_value; - return; - } - } - - } break; - case QUAT: { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - Quat *v = reinterpret_cast<Quat *>(_data._mem); - if (*str == "x") { - valid = true; - v->x = p_value; - return; - } else if (*str == "y") { - valid = true; - v->y = p_value; - return; - } else if (*str == "z") { - valid = true; - v->z = p_value; - return; - } else if (*str == "w") { - valid = true; - v->w = p_value; - return; - } - } - - } break; - case AABB: { - if (p_value.type != Variant::VECTOR3) { - return; - } - - if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - ::AABB *v = _data._aabb; - if (*str == "position") { - valid = true; - v->position = p_value; - return; - } else if (*str == "size") { - valid = true; - v->size = p_value; - return; - } else if (*str == "end") { - valid = true; - v->size = Vector3(p_value) - v->position; - return; - } - } - } break; - case BASIS: { - if (p_value.type != Variant::VECTOR3) { - return; - } - - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - - if (index < 0) { - index += 3; - } - if (index >= 0 && index < 3) { - Basis *v = _data._basis; - - valid = true; - v->set_axis(index, p_value); - return; - } - } else if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - Basis *v = _data._basis; - - if (*str == "x") { - valid = true; - v->set_axis(0, p_value); - return; - } else if (*str == "y") { - valid = true; - v->set_axis(1, p_value); - return; - } else if (*str == "z") { - valid = true; - v->set_axis(2, p_value); - return; - } - } - - } break; - case TRANSFORM: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - if (p_value.type != Variant::VECTOR3) { - return; - } - - int index = p_index; - - if (index < 0) { - index += 4; - } - if (index >= 0 && index < 4) { - Transform *v = _data._transform; - valid = true; - if (index == 3) { - v->origin = p_value; - } else { - v->basis.set_axis(index, p_value); - } - return; - } - } else if (p_index.get_type() == Variant::STRING) { - Transform *v = _data._transform; - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - - if (*str == "basis") { - if (p_value.type != Variant::BASIS) { - return; - } - valid = true; - v->basis = p_value; - return; - } - if (*str == "origin") { - if (p_value.type != Variant::VECTOR3) { - return; - } - valid = true; - v->origin = p_value; - return; - } - } - - } break; - case COLOR: { - if (p_value.type != Variant::INT && p_value.type != Variant::FLOAT) { - return; - } - - if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - Color *v = reinterpret_cast<Color *>(_data._mem); - if (*str == "r") { - valid = true; - v->r = p_value; - return; - } else if (*str == "g") { - valid = true; - v->g = p_value; - return; - } else if (*str == "b") { - valid = true; - v->b = p_value; - return; - } else if (*str == "a") { - valid = true; - v->a = p_value; - return; - } else if (*str == "h") { - valid = true; - v->set_hsv(p_value, v->get_s(), v->get_v(), v->a); - return; - } else if (*str == "s") { - valid = true; - v->set_hsv(v->get_h(), p_value, v->get_v(), v->a); - return; - } else if (*str == "v") { - valid = true; - v->set_hsv(v->get_h(), v->get_s(), p_value, v->a); - return; - } else if (*str == "r8") { - valid = true; - v->r = float(p_value) / 255.0; - return; - } else if (*str == "g8") { - valid = true; - v->g = float(p_value) / 255.0; - return; - } else if (*str == "b8") { - valid = true; - v->b = float(p_value) / 255.0; - return; - } else if (*str == "a8") { - valid = true; - v->a = float(p_value) / 255.0; - return; - } - } else if (p_index.get_type() == Variant::INT) { - int idx = p_index; - if (idx < 0) { - idx += 4; - } - if (idx >= 0 && idx < 4) { - Color *v = reinterpret_cast<Color *>(_data._mem); - (*v)[idx] = p_value; - valid = true; - } - } - - } break; - case STRING_NAME: { - } break; - case NODE_PATH: { - } break; - case _RID: { - } break; - case OBJECT: { - Object *obj = _get_obj().obj; - //only if debugging! - - if (obj) { -#ifdef DEBUG_ENABLED - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - WARN_PRINT("Attempted use of previously freed pointer object."); - valid = false; - return; - } -#endif - - if (p_index.get_type() != Variant::STRING_NAME && p_index.get_type() != Variant::STRING) { - obj->setvar(p_index, p_value, r_valid); - return; - } - - obj->set(p_index, p_value, r_valid); - return; - } - } break; - case DICTIONARY: { - Dictionary *dic = reinterpret_cast<Dictionary *>(_data._mem); - dic->operator[](p_index) = p_value; - valid = true; //always valid, i guess? should this really be ok? - return; - } break; - DEFAULT_OP_ARRAY_CMD(ARRAY, Array, ;, (*arr)[index] = p_value; return ) - DEFAULT_OP_DVECTOR_SET(PACKED_BYTE_ARRAY, uint8_t, p_value.type != Variant::FLOAT && p_value.type != Variant::INT) - DEFAULT_OP_DVECTOR_SET(PACKED_INT32_ARRAY, int32_t, p_value.type != Variant::FLOAT && p_value.type != Variant::INT) - DEFAULT_OP_DVECTOR_SET(PACKED_INT64_ARRAY, int64_t, p_value.type != Variant::FLOAT && p_value.type != Variant::INT) - DEFAULT_OP_DVECTOR_SET(PACKED_FLOAT32_ARRAY, float, p_value.type != Variant::FLOAT && p_value.type != Variant::INT) - DEFAULT_OP_DVECTOR_SET(PACKED_FLOAT64_ARRAY, double, p_value.type != Variant::FLOAT && p_value.type != Variant::INT) - DEFAULT_OP_DVECTOR_SET(PACKED_STRING_ARRAY, String, p_value.type != Variant::STRING) - DEFAULT_OP_DVECTOR_SET(PACKED_VECTOR2_ARRAY, Vector2, p_value.type != Variant::VECTOR2) - DEFAULT_OP_DVECTOR_SET(PACKED_VECTOR3_ARRAY, Vector3, p_value.type != Variant::VECTOR3) - DEFAULT_OP_DVECTOR_SET(PACKED_COLOR_ARRAY, Color, p_value.type != Variant::COLOR) - default: - return; - } -} - -Variant Variant::get(const Variant &p_index, bool *r_valid) const { - static bool _dummy = false; - - bool &valid = r_valid ? *r_valid : _dummy; - - valid = false; - - switch (type) { - case NIL: { - return Variant(); - } break; - case BOOL: { - return Variant(); - } break; - case INT: { - return Variant(); - } break; - case FLOAT: { - return Variant(); - } break; - case STRING: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - //string index - - int idx = p_index; - const String *str = reinterpret_cast<const String *>(_data._mem); - if (idx < 0) { - idx += str->length(); - } - if (idx >= 0 && idx < str->length()) { - valid = true; - return str->substr(idx, 1); - } - } - - } break; - case VECTOR2: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - // scalar index - int idx = p_index; - if (idx < 0) { - idx += 2; - } - if (idx >= 0 && idx < 2) { - const Vector2 *v = reinterpret_cast<const Vector2 *>(_data._mem); - valid = true; - return (*v)[idx]; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - const Vector2 *v = reinterpret_cast<const Vector2 *>(_data._mem); - if (*str == "x") { - valid = true; - return v->x; - } else if (*str == "y") { - valid = true; - return v->y; - } - } - - } break; - case VECTOR2I: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - // scalar index - int idx = p_index; - if (idx < 0) { - idx += 2; - } - if (idx >= 0 && idx < 2) { - const Vector2i *v = reinterpret_cast<const Vector2i *>(_data._mem); - valid = true; - return (*v)[idx]; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - const Vector2i *v = reinterpret_cast<const Vector2i *>(_data._mem); - if (*str == "x") { - valid = true; - return v->x; - } else if (*str == "y") { - valid = true; - return v->y; - } - } - - } break; - case RECT2: { - if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - const Rect2 *v = reinterpret_cast<const Rect2 *>(_data._mem); - if (*str == "position") { - valid = true; - return v->position; - } else if (*str == "size") { - valid = true; - return v->size; - } else if (*str == "end") { - valid = true; - return v->size + v->position; - } - } - } break; - case RECT2I: { - if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - const Rect2i *v = reinterpret_cast<const Rect2i *>(_data._mem); - if (*str == "position") { - valid = true; - return v->position; - } else if (*str == "size") { - valid = true; - return v->size; - } else if (*str == "end") { - valid = true; - return v->size + v->position; - } - } - } break; - case VECTOR3: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - //scalar index - int idx = p_index; - if (idx < 0) { - idx += 3; - } - if (idx >= 0 && idx < 3) { - const Vector3 *v = reinterpret_cast<const Vector3 *>(_data._mem); - valid = true; - return (*v)[idx]; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - const Vector3 *v = reinterpret_cast<const Vector3 *>(_data._mem); - if (*str == "x") { - valid = true; - return v->x; - } else if (*str == "y") { - valid = true; - return v->y; - } else if (*str == "z") { - valid = true; - return v->z; - } - } - - } break; - case VECTOR3I: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - //scalar index - int idx = p_index; - if (idx < 0) { - idx += 3; - } - if (idx >= 0 && idx < 3) { - const Vector3i *v = reinterpret_cast<const Vector3i *>(_data._mem); - valid = true; - return (*v)[idx]; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - const Vector3i *v = reinterpret_cast<const Vector3i *>(_data._mem); - if (*str == "x") { - valid = true; - return v->x; - } else if (*str == "y") { - valid = true; - return v->y; - } else if (*str == "z") { - valid = true; - return v->z; - } - } - - } break; - case TRANSFORM2D: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - - if (index < 0) { - index += 3; - } - if (index >= 0 && index < 3) { - const Transform2D *v = _data._transform2d; - - valid = true; - return v->elements[index]; - } - } else if (p_index.get_type() == Variant::STRING) { - //scalar name - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - const Transform2D *v = _data._transform2d; - if (*str == "x") { - valid = true; - return v->elements[0]; - } else if (*str == "y") { - valid = true; - return v->elements[1]; - } else if (*str == "origin") { - valid = true; - return v->elements[2]; - } - } - - } break; - case PLANE: { - if (p_index.get_type() == Variant::STRING) { - //scalar name - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - const Plane *v = reinterpret_cast<const Plane *>(_data._mem); - if (*str == "x") { - valid = true; - return v->normal.x; - } else if (*str == "y") { - valid = true; - return v->normal.y; - } else if (*str == "z") { - valid = true; - return v->normal.z; - } else if (*str == "normal") { - valid = true; - return v->normal; - } else if (*str == "d") { - valid = true; - return v->d; - } - } - - } break; - case QUAT: { - if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - const Quat *v = reinterpret_cast<const Quat *>(_data._mem); - if (*str == "x") { - valid = true; - return v->x; - } else if (*str == "y") { - valid = true; - return v->y; - } else if (*str == "z") { - valid = true; - return v->z; - } else if (*str == "w") { - valid = true; - return v->w; - } - } - - } break; - case AABB: { - if (p_index.get_type() == Variant::STRING) { - //scalar name - - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - const ::AABB *v = _data._aabb; - if (*str == "position") { - valid = true; - return v->position; - } else if (*str == "size") { - valid = true; - return v->size; - } else if (*str == "end") { - valid = true; - return v->size + v->position; - } - } - } break; - case BASIS: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - if (index < 0) { - index += 3; - } - if (index >= 0 && index < 3) { - const Basis *v = _data._basis; - - valid = true; - return v->get_axis(index); - } - } else if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - const Basis *v = _data._basis; - - if (*str == "x") { - valid = true; - return v->get_axis(0); - } else if (*str == "y") { - valid = true; - return v->get_axis(1); - } else if (*str == "z") { - valid = true; - return v->get_axis(2); - } - } - - } break; - case TRANSFORM: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - if (index < 0) { - index += 4; - } - if (index >= 0 && index < 4) { - const Transform *v = _data._transform; - valid = true; - return index == 3 ? v->origin : v->basis.get_axis(index); - } - } else if (p_index.get_type() == Variant::STRING) { - const Transform *v = _data._transform; - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - - if (*str == "basis") { - valid = true; - return v->basis; - } - if (*str == "origin") { - valid = true; - return v->origin; - } - } - - } break; - case COLOR: { - if (p_index.get_type() == Variant::STRING) { - const String *str = reinterpret_cast<const String *>(p_index._data._mem); - const Color *v = reinterpret_cast<const Color *>(_data._mem); - if (*str == "r") { - valid = true; - return v->r; - } else if (*str == "g") { - valid = true; - return v->g; - } else if (*str == "b") { - valid = true; - return v->b; - } else if (*str == "a") { - valid = true; - return v->a; - } else if (*str == "h") { - valid = true; - return v->get_h(); - } else if (*str == "s") { - valid = true; - return v->get_s(); - } else if (*str == "v") { - valid = true; - return v->get_v(); - } else if (*str == "r8") { - valid = true; - return (int)Math::round(v->r * 255.0); - } else if (*str == "g8") { - valid = true; - return (int)Math::round(v->g * 255.0); - } else if (*str == "b8") { - valid = true; - return (int)Math::round(v->b * 255.0); - } else if (*str == "a8") { - valid = true; - return (int)Math::round(v->a * 255.0); - } - } else if (p_index.get_type() == Variant::INT) { - int idx = p_index; - if (idx < 0) { - idx += 4; - } - if (idx >= 0 && idx < 4) { - const Color *v = reinterpret_cast<const Color *>(_data._mem); - valid = true; - return (*v)[idx]; - } - } - - } break; - case STRING_NAME: { - } break; - case NODE_PATH: { - } break; - case _RID: { - } break; - case OBJECT: { - Object *obj = _get_obj().obj; - if (obj) { -#ifdef DEBUG_ENABLED - - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - valid = false; - return "Attempted get on previously freed instance."; - } -#endif - - if (p_index.get_type() != Variant::STRING) { - return obj->getvar(p_index, r_valid); - } - - return obj->get(p_index, r_valid); - } - - } break; - case DICTIONARY: { - const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem); - const Variant *res = dic->getptr(p_index); - if (res) { - valid = true; - return *res; - } - } break; - DEFAULT_OP_ARRAY_CMD(ARRAY, const Array, ;, return (*arr)[index]) - DEFAULT_OP_DVECTOR_GET(PACKED_BYTE_ARRAY, uint8_t) - DEFAULT_OP_DVECTOR_GET(PACKED_INT32_ARRAY, int32_t) - DEFAULT_OP_DVECTOR_GET(PACKED_INT64_ARRAY, int64_t) - DEFAULT_OP_DVECTOR_GET(PACKED_FLOAT32_ARRAY, float) - DEFAULT_OP_DVECTOR_GET(PACKED_FLOAT64_ARRAY, double) - DEFAULT_OP_DVECTOR_GET(PACKED_STRING_ARRAY, String) - DEFAULT_OP_DVECTOR_GET(PACKED_VECTOR2_ARRAY, Vector2) - DEFAULT_OP_DVECTOR_GET(PACKED_VECTOR3_ARRAY, Vector3) - DEFAULT_OP_DVECTOR_GET(PACKED_COLOR_ARRAY, Color) - default: - return Variant(); - } - - return Variant(); -} - -bool Variant::in(const Variant &p_index, bool *r_valid) const { - if (r_valid) { - *r_valid = true; - } - - switch (type) { - case STRING: { - if (p_index.get_type() == Variant::STRING) { - //string index - String idx = p_index; - const String *str = reinterpret_cast<const String *>(_data._mem); - - return str->find(idx) != -1; - } - - } break; - case OBJECT: { - Object *obj = _get_obj().obj; - if (obj) { - bool valid = false; -#ifdef DEBUG_ENABLED - - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - if (r_valid) { - *r_valid = false; - } - return true; // Attempted get on stray pointer. - } - -#endif - - if (p_index.get_type() != Variant::STRING) { - obj->getvar(p_index, &valid); - } else { - obj->get(p_index, &valid); - } - - return valid; - } else { - if (r_valid) { - *r_valid = false; - } - } - return false; - } break; - case DICTIONARY: { - const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem); - return dic->has(p_index); - - } break; - case ARRAY: { - const Array *arr = reinterpret_cast<const Array *>(_data._mem); - int l = arr->size(); - if (l) { - for (int i = 0; i < l; i++) { - if (evaluate(OP_EQUAL, (*arr)[i], p_index)) { - return true; - } - } - } - - return false; - - } break; - case PACKED_BYTE_ARRAY: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int index = p_index; - const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array); - int l = arr->size(); - if (l) { - const uint8_t *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - - } break; - case PACKED_INT32_ARRAY: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int32_t index = p_index; - const Vector<int32_t> *arr = &PackedArrayRef<int32_t>::get_array(_data.packed_array); - int32_t l = arr->size(); - if (l) { - const int32_t *r = arr->ptr(); - for (int32_t i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - } break; - case PACKED_INT64_ARRAY: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - int64_t index = p_index; - const Vector<int64_t> *arr = &PackedArrayRef<int64_t>::get_array(_data.packed_array); - int64_t l = arr->size(); - if (l) { - const int64_t *r = arr->ptr(); - for (int64_t i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - } break; - case PACKED_FLOAT32_ARRAY: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - real_t index = p_index; - const Vector<float> *arr = &PackedArrayRef<float>::get_array(_data.packed_array); - int l = arr->size(); - if (l) { - const float *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - - } break; - case PACKED_FLOAT64_ARRAY: { - if (p_index.get_type() == Variant::INT || p_index.get_type() == Variant::FLOAT) { - real_t index = p_index; - const Vector<double> *arr = &PackedArrayRef<double>::get_array(_data.packed_array); - int l = arr->size(); - if (l) { - const double *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - - } break; - case PACKED_STRING_ARRAY: { - if (p_index.get_type() == Variant::STRING) { - String index = p_index; - const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array); - - int l = arr->size(); - if (l) { - const String *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - - } break; //25 - case PACKED_VECTOR2_ARRAY: { - if (p_index.get_type() == Variant::VECTOR2) { - Vector2 index = p_index; - const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array); - - int l = arr->size(); - if (l) { - const Vector2 *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - - } break; - case PACKED_VECTOR3_ARRAY: { - if (p_index.get_type() == Variant::VECTOR3) { - Vector3 index = p_index; - const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array); - - int l = arr->size(); - if (l) { - const Vector3 *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - - } break; - case PACKED_COLOR_ARRAY: { - if (p_index.get_type() == Variant::COLOR) { - Color index = p_index; - const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array); - - int l = arr->size(); - if (l) { - const Color *r = arr->ptr(); - for (int i = 0; i < l; i++) { - if (r[i] == index) { - return true; - } - } - } - - return false; - } - } break; - default: { - } - } - - if (r_valid) { - *r_valid = false; - } - return false; -} - -void Variant::get_property_list(List<PropertyInfo> *p_list) const { - switch (type) { - case VECTOR2: { - p_list->push_back(PropertyInfo(Variant::FLOAT, "x")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "y")); - - } break; - case VECTOR2I: { - p_list->push_back(PropertyInfo(Variant::INT, "x")); - p_list->push_back(PropertyInfo(Variant::INT, "y")); - - } break; - case RECT2: { - p_list->push_back(PropertyInfo(Variant::VECTOR2, "position")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, "size")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, "end")); - - } break; - case RECT2I: { - p_list->push_back(PropertyInfo(Variant::VECTOR2I, "position")); - p_list->push_back(PropertyInfo(Variant::VECTOR2I, "size")); - p_list->push_back(PropertyInfo(Variant::VECTOR2I, "end")); - - } break; - case VECTOR3: { - p_list->push_back(PropertyInfo(Variant::FLOAT, "x")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "y")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "z")); - - } break; - case VECTOR3I: { - p_list->push_back(PropertyInfo(Variant::INT, "x")); - p_list->push_back(PropertyInfo(Variant::INT, "y")); - p_list->push_back(PropertyInfo(Variant::INT, "z")); - - } break; - case TRANSFORM2D: { - p_list->push_back(PropertyInfo(Variant::VECTOR2, "x")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, "y")); - p_list->push_back(PropertyInfo(Variant::VECTOR2, "origin")); - - } break; - case PLANE: { - p_list->push_back(PropertyInfo(Variant::VECTOR3, "normal")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "x")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "y")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "z")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "d")); - - } break; - case QUAT: { - p_list->push_back(PropertyInfo(Variant::FLOAT, "x")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "y")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "z")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "w")); - - } break; - case AABB: { - p_list->push_back(PropertyInfo(Variant::VECTOR3, "position")); - p_list->push_back(PropertyInfo(Variant::VECTOR3, "size")); - p_list->push_back(PropertyInfo(Variant::VECTOR3, "end")); - } break; - case BASIS: { - p_list->push_back(PropertyInfo(Variant::VECTOR3, "x")); - p_list->push_back(PropertyInfo(Variant::VECTOR3, "y")); - p_list->push_back(PropertyInfo(Variant::VECTOR3, "z")); - - } break; - case TRANSFORM: { - p_list->push_back(PropertyInfo(Variant::BASIS, "basis")); - p_list->push_back(PropertyInfo(Variant::VECTOR3, "origin")); - - } break; - case COLOR: { - p_list->push_back(PropertyInfo(Variant::FLOAT, "r")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "g")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "b")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "a")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "h")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "s")); - p_list->push_back(PropertyInfo(Variant::FLOAT, "v")); - p_list->push_back(PropertyInfo(Variant::INT, "r8")); - p_list->push_back(PropertyInfo(Variant::INT, "g8")); - p_list->push_back(PropertyInfo(Variant::INT, "b8")); - p_list->push_back(PropertyInfo(Variant::INT, "a8")); - - } break; - case STRING_NAME: { - } break; - case NODE_PATH: { - } break; - case _RID: { - } break; - case OBJECT: { - Object *obj = _get_obj().obj; - if (obj) { -#ifdef DEBUG_ENABLED - - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - WARN_PRINT("Attempted get_property list on previously freed instance."); - return; - } - -#endif - - obj->get_property_list(p_list); - } - - } break; - case DICTIONARY: { - const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem); - List<Variant> keys; - dic->get_key_list(&keys); - for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - if (E->get().get_type() == Variant::STRING) { - p_list->push_back(PropertyInfo(Variant::STRING, E->get())); - } - } - } break; - case ARRAY: - case PACKED_BYTE_ARRAY: - case PACKED_INT32_ARRAY: - case PACKED_INT64_ARRAY: - case PACKED_FLOAT32_ARRAY: - case PACKED_FLOAT64_ARRAY: - case PACKED_STRING_ARRAY: - case PACKED_VECTOR2_ARRAY: - case PACKED_VECTOR3_ARRAY: - case PACKED_COLOR_ARRAY: { - //nothing - } break; - default: { - } - } -} - -bool Variant::iter_init(Variant &r_iter, bool &valid) const { - valid = true; - switch (type) { - case INT: { - r_iter = 0; - return _data._int > 0; - } break; - case FLOAT: { - r_iter = 0; - return _data._float > 0.0; - } break; - case VECTOR2: { - double from = reinterpret_cast<const Vector2 *>(_data._mem)->x; - double to = reinterpret_cast<const Vector2 *>(_data._mem)->y; - - r_iter = from; - - return from < to; - } break; - case VECTOR2I: { - int64_t from = reinterpret_cast<const Vector2i *>(_data._mem)->x; - int64_t to = reinterpret_cast<const Vector2i *>(_data._mem)->y; - - r_iter = from; - - return from < to; - } break; - case VECTOR3: { - double from = reinterpret_cast<const Vector3 *>(_data._mem)->x; - double to = reinterpret_cast<const Vector3 *>(_data._mem)->y; - double step = reinterpret_cast<const Vector3 *>(_data._mem)->z; - - r_iter = from; - - if (from == to) { - return false; - } else if (from < to) { - return step > 0; - } - return step < 0; - } break; - case VECTOR3I: { - int64_t from = reinterpret_cast<const Vector3i *>(_data._mem)->x; - int64_t to = reinterpret_cast<const Vector3i *>(_data._mem)->y; - int64_t step = reinterpret_cast<const Vector3i *>(_data._mem)->z; - - r_iter = from; - - if (from == to) { - return false; - } else if (from < to) { - return step > 0; - } - return step < 0; - } break; - case OBJECT: { - if (!_get_obj().obj) { - valid = false; - return false; - } - -#ifdef DEBUG_ENABLED - - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - valid = false; - return false; - } - -#endif - Callable::CallError ce; - ce.error = Callable::CallError::CALL_OK; - Array ref; - ref.push_back(r_iter); - Variant vref = ref; - const Variant *refp[] = { &vref }; - Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_init, refp, 1, ce); - - if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) { - valid = false; - return false; - } - - r_iter = ref[0]; - return ret; - } break; - - case STRING: { - const String *str = reinterpret_cast<const String *>(_data._mem); - if (str->empty()) { - return false; - } - r_iter = 0; - return true; - } break; - case DICTIONARY: { - const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem); - if (dic->empty()) { - return false; - } - - const Variant *next = dic->next(nullptr); - r_iter = *next; - return true; - - } break; - case ARRAY: { - const Array *arr = reinterpret_cast<const Array *>(_data._mem); - if (arr->empty()) { - return false; - } - r_iter = 0; - return true; - } break; - case PACKED_BYTE_ARRAY: { - const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array); - if (arr->size() == 0) { - return false; - } - r_iter = 0; - return true; - - } break; - case PACKED_INT32_ARRAY: { - const Vector<int32_t> *arr = &PackedArrayRef<int32_t>::get_array(_data.packed_array); - if (arr->size() == 0) { - return false; - } - r_iter = 0; - return true; - - } break; - case PACKED_INT64_ARRAY: { - const Vector<int64_t> *arr = &PackedArrayRef<int64_t>::get_array(_data.packed_array); - if (arr->size() == 0) { - return false; - } - r_iter = 0; - return true; - - } break; - case PACKED_FLOAT32_ARRAY: { - const Vector<float> *arr = &PackedArrayRef<float>::get_array(_data.packed_array); - if (arr->size() == 0) { - return false; - } - r_iter = 0; - return true; - - } break; - case PACKED_FLOAT64_ARRAY: { - const Vector<double> *arr = &PackedArrayRef<double>::get_array(_data.packed_array); - if (arr->size() == 0) { - return false; - } - r_iter = 0; - return true; - - } break; - case PACKED_STRING_ARRAY: { - const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array); - if (arr->size() == 0) { - return false; - } - r_iter = 0; - return true; - } break; - case PACKED_VECTOR2_ARRAY: { - const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array); - if (arr->size() == 0) { - return false; - } - r_iter = 0; - return true; - } break; - case PACKED_VECTOR3_ARRAY: { - const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array); - if (arr->size() == 0) { - return false; - } - r_iter = 0; - return true; - } break; - case PACKED_COLOR_ARRAY: { - const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array); - if (arr->size() == 0) { - return false; - } - r_iter = 0; - return true; - - } break; - default: { - } - } - - valid = false; - return false; -} - -bool Variant::iter_next(Variant &r_iter, bool &valid) const { - valid = true; - switch (type) { - case INT: { - int64_t idx = r_iter; - idx++; - if (idx >= _data._int) { - return false; - } - r_iter = idx; - return true; - } break; - case FLOAT: { - int64_t idx = r_iter; - idx++; - if (idx >= _data._float) { - return false; - } - r_iter = idx; - return true; - } break; - case VECTOR2: { - double to = reinterpret_cast<const Vector2 *>(_data._mem)->y; - - double idx = r_iter; - idx++; - - if (idx >= to) { - return false; - } - - r_iter = idx; - return true; - } break; - case VECTOR2I: { - int64_t to = reinterpret_cast<const Vector2i *>(_data._mem)->y; - - int64_t idx = r_iter; - idx++; - - if (idx >= to) { - return false; - } - - r_iter = idx; - return true; - } break; - case VECTOR3: { - double to = reinterpret_cast<const Vector3 *>(_data._mem)->y; - double step = reinterpret_cast<const Vector3 *>(_data._mem)->z; - - double idx = r_iter; - idx += step; - - if (step < 0 && idx <= to) { - return false; - } - - if (step > 0 && idx >= to) { - return false; - } - - r_iter = idx; - return true; - } break; - case VECTOR3I: { - int64_t to = reinterpret_cast<const Vector3i *>(_data._mem)->y; - int64_t step = reinterpret_cast<const Vector3i *>(_data._mem)->z; - - int64_t idx = r_iter; - idx += step; - - if (step < 0 && idx <= to) { - return false; - } - - if (step > 0 && idx >= to) { - return false; - } - - r_iter = idx; - return true; - } break; - case OBJECT: { - if (!_get_obj().obj) { - valid = false; - return false; - } - -#ifdef DEBUG_ENABLED - - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - valid = false; - return false; - } - -#endif - Callable::CallError ce; - ce.error = Callable::CallError::CALL_OK; - Array ref; - ref.push_back(r_iter); - Variant vref = ref; - const Variant *refp[] = { &vref }; - Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_next, refp, 1, ce); - - if (ref.size() != 1 || ce.error != Callable::CallError::CALL_OK) { - valid = false; - return false; - } - - r_iter = ref[0]; - - return ret; - } break; - - case STRING: { - const String *str = reinterpret_cast<const String *>(_data._mem); - int idx = r_iter; - idx++; - if (idx >= str->length()) { - return false; - } - r_iter = idx; - return true; - } break; - case DICTIONARY: { - const Dictionary *dic = reinterpret_cast<const Dictionary *>(_data._mem); - const Variant *next = dic->next(&r_iter); - if (!next) { - return false; - } - - r_iter = *next; - return true; - - } break; - case ARRAY: { - const Array *arr = reinterpret_cast<const Array *>(_data._mem); - int idx = r_iter; - idx++; - if (idx >= arr->size()) { - return false; - } - r_iter = idx; - return true; - } break; - case PACKED_BYTE_ARRAY: { - const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array); - int idx = r_iter; - idx++; - if (idx >= arr->size()) { - return false; - } - r_iter = idx; - return true; - - } break; - case PACKED_INT32_ARRAY: { - const Vector<int32_t> *arr = &PackedArrayRef<int32_t>::get_array(_data.packed_array); - int32_t idx = r_iter; - idx++; - if (idx >= arr->size()) { - return false; - } - r_iter = idx; - return true; - - } break; - case PACKED_INT64_ARRAY: { - const Vector<int64_t> *arr = &PackedArrayRef<int64_t>::get_array(_data.packed_array); - int64_t idx = r_iter; - idx++; - if (idx >= arr->size()) { - return false; - } - r_iter = idx; - return true; - - } break; - case PACKED_FLOAT32_ARRAY: { - const Vector<float> *arr = &PackedArrayRef<float>::get_array(_data.packed_array); - int idx = r_iter; - idx++; - if (idx >= arr->size()) { - return false; - } - r_iter = idx; - return true; - - } break; - case PACKED_FLOAT64_ARRAY: { - const Vector<double> *arr = &PackedArrayRef<double>::get_array(_data.packed_array); - int idx = r_iter; - idx++; - if (idx >= arr->size()) { - return false; - } - r_iter = idx; - return true; - - } break; - case PACKED_STRING_ARRAY: { - const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array); - int idx = r_iter; - idx++; - if (idx >= arr->size()) { - return false; - } - r_iter = idx; - return true; - } break; - case PACKED_VECTOR2_ARRAY: { - const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array); - int idx = r_iter; - idx++; - if (idx >= arr->size()) { - return false; - } - r_iter = idx; - return true; - } break; - case PACKED_VECTOR3_ARRAY: { - const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array); - int idx = r_iter; - idx++; - if (idx >= arr->size()) { - return false; - } - r_iter = idx; - return true; - } break; - case PACKED_COLOR_ARRAY: { - const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array); - int idx = r_iter; - idx++; - if (idx >= arr->size()) { - return false; - } - r_iter = idx; - return true; - } break; - default: { - } - } - - valid = false; - return false; -} - -Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { - r_valid = true; - switch (type) { - case INT: { - return r_iter; - } break; - case FLOAT: { - return r_iter; - } break; - case VECTOR2: { - return r_iter; - } break; - case VECTOR2I: { - return r_iter; - } break; - case VECTOR3: { - return r_iter; - } break; - case VECTOR3I: { - return r_iter; - } break; - case OBJECT: { - if (!_get_obj().obj) { - r_valid = false; - return Variant(); - } -#ifdef DEBUG_ENABLED - if (EngineDebugger::is_active() && !_get_obj().id.is_reference() && ObjectDB::get_instance(_get_obj().id) == nullptr) { - r_valid = false; - return Variant(); - } - -#endif - Callable::CallError ce; - ce.error = Callable::CallError::CALL_OK; - const Variant *refp[] = { &r_iter }; - Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_get, refp, 1, ce); - - if (ce.error != Callable::CallError::CALL_OK) { - r_valid = false; - return Variant(); - } - - //r_iter=ref[0]; - - return ret; - } break; - - case STRING: { - const String *str = reinterpret_cast<const String *>(_data._mem); - return str->substr(r_iter, 1); - } break; - case DICTIONARY: { - return r_iter; //iterator is the same as the key - - } break; - case ARRAY: { - const Array *arr = reinterpret_cast<const Array *>(_data._mem); - int idx = r_iter; -#ifdef DEBUG_ENABLED - if (idx < 0 || idx >= arr->size()) { - r_valid = false; - return Variant(); - } -#endif - return arr->get(idx); - } break; - case PACKED_BYTE_ARRAY: { - const Vector<uint8_t> *arr = &PackedArrayRef<uint8_t>::get_array(_data.packed_array); - int idx = r_iter; -#ifdef DEBUG_ENABLED - if (idx < 0 || idx >= arr->size()) { - r_valid = false; - return Variant(); - } -#endif - return arr->get(idx); - } break; - case PACKED_INT32_ARRAY: { - const Vector<int32_t> *arr = &PackedArrayRef<int32_t>::get_array(_data.packed_array); - int32_t idx = r_iter; -#ifdef DEBUG_ENABLED - if (idx < 0 || idx >= arr->size()) { - r_valid = false; - return Variant(); - } -#endif - return arr->get(idx); - } break; - case PACKED_INT64_ARRAY: { - const Vector<int64_t> *arr = &PackedArrayRef<int64_t>::get_array(_data.packed_array); - int64_t idx = r_iter; -#ifdef DEBUG_ENABLED - if (idx < 0 || idx >= arr->size()) { - r_valid = false; - return Variant(); - } -#endif - return arr->get(idx); - } break; - case PACKED_FLOAT32_ARRAY: { - const Vector<float> *arr = &PackedArrayRef<float>::get_array(_data.packed_array); - int idx = r_iter; -#ifdef DEBUG_ENABLED - if (idx < 0 || idx >= arr->size()) { - r_valid = false; - return Variant(); - } -#endif - return arr->get(idx); - } break; - case PACKED_FLOAT64_ARRAY: { - const Vector<double> *arr = &PackedArrayRef<double>::get_array(_data.packed_array); - int idx = r_iter; -#ifdef DEBUG_ENABLED - if (idx < 0 || idx >= arr->size()) { - r_valid = false; - return Variant(); - } -#endif - return arr->get(idx); - } break; - case PACKED_STRING_ARRAY: { - const Vector<String> *arr = &PackedArrayRef<String>::get_array(_data.packed_array); - int idx = r_iter; -#ifdef DEBUG_ENABLED - if (idx < 0 || idx >= arr->size()) { - r_valid = false; - return Variant(); - } -#endif - return arr->get(idx); - } break; - case PACKED_VECTOR2_ARRAY: { - const Vector<Vector2> *arr = &PackedArrayRef<Vector2>::get_array(_data.packed_array); - int idx = r_iter; -#ifdef DEBUG_ENABLED - if (idx < 0 || idx >= arr->size()) { - r_valid = false; - return Variant(); - } -#endif - return arr->get(idx); - } break; - case PACKED_VECTOR3_ARRAY: { - const Vector<Vector3> *arr = &PackedArrayRef<Vector3>::get_array(_data.packed_array); - int idx = r_iter; -#ifdef DEBUG_ENABLED - if (idx < 0 || idx >= arr->size()) { - r_valid = false; - return Variant(); - } -#endif - return arr->get(idx); - } break; - case PACKED_COLOR_ARRAY: { - const Vector<Color> *arr = &PackedArrayRef<Color>::get_array(_data.packed_array); - int idx = r_iter; -#ifdef DEBUG_ENABLED - if (idx < 0 || idx >= arr->size()) { - r_valid = false; - return Variant(); - } -#endif - return arr->get(idx); - } break; - default: { - } - } - - r_valid = false; - return Variant(); -} - -Variant Variant::duplicate(bool deep) const { - switch (type) { - case OBJECT: { - /* breaks stuff :( - if (deep && !_get_obj().ref.is_null()) { - Ref<Resource> resource = _get_obj().ref; - if (resource.is_valid()) { - return resource->duplicate(true); - } - } - */ - return *this; - } break; - case DICTIONARY: - return operator Dictionary().duplicate(deep); - case ARRAY: - return operator Array().duplicate(deep); - default: - return *this; - } -} - -void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst) { - if (a.type != b.type) { - if (a.is_num() && b.is_num()) { - real_t va = a; - real_t vb = b; - r_dst = va + vb * c; - } else { - r_dst = a; - } - return; - } - - switch (a.type) { - case NIL: { - r_dst = Variant(); - } - return; - case INT: { - int64_t va = a._data._int; - int64_t vb = b._data._int; - r_dst = int(va + vb * c + 0.5); - } - return; - case FLOAT: { - double ra = a._data._float; - double rb = b._data._float; - r_dst = ra + rb * c; - } - return; - case VECTOR2: { - r_dst = *reinterpret_cast<const Vector2 *>(a._data._mem) + *reinterpret_cast<const Vector2 *>(b._data._mem) * c; - } - return; - case VECTOR2I: { - int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x; - int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x; - int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y; - int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y; - r_dst = Vector2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5)); - } - return; - case RECT2: { - const Rect2 *ra = reinterpret_cast<const Rect2 *>(a._data._mem); - const Rect2 *rb = reinterpret_cast<const Rect2 *>(b._data._mem); - r_dst = Rect2(ra->position + rb->position * c, ra->size + rb->size * c); - } - return; - case RECT2I: { - const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem); - const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem); - - int32_t vax = ra->position.x; - int32_t vay = ra->position.y; - int32_t vbx = ra->size.x; - int32_t vby = ra->size.y; - int32_t vcx = rb->position.x; - int32_t vcy = rb->position.y; - int32_t vdx = rb->size.x; - int32_t vdy = rb->size.y; - - r_dst = Rect2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vcx + vdx * c + 0.5), int32_t(vcy + vdy * c + 0.5)); - } - return; - case VECTOR3: { - r_dst = *reinterpret_cast<const Vector3 *>(a._data._mem) + *reinterpret_cast<const Vector3 *>(b._data._mem) * c; - } - return; - case VECTOR3I: { - int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x; - int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x; - int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y; - int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y; - int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z; - int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z; - r_dst = Vector3i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vaz + vbz * c + 0.5)); - } - return; - case AABB: { - const ::AABB *ra = reinterpret_cast<const ::AABB *>(a._data._mem); - const ::AABB *rb = reinterpret_cast<const ::AABB *>(b._data._mem); - r_dst = ::AABB(ra->position + rb->position * c, ra->size + rb->size * c); - } - return; - case QUAT: { - Quat empty_rot; - const Quat *qa = reinterpret_cast<const Quat *>(a._data._mem); - const Quat *qb = reinterpret_cast<const Quat *>(b._data._mem); - r_dst = *qa * empty_rot.slerp(*qb, c); - } - return; - case COLOR: { - const Color *ca = reinterpret_cast<const Color *>(a._data._mem); - const Color *cb = reinterpret_cast<const Color *>(b._data._mem); - float new_r = ca->r + cb->r * c; - float new_g = ca->g + cb->g * c; - float new_b = ca->b + cb->b * c; - float new_a = ca->a + cb->a * c; - new_r = new_r > 1.0 ? 1.0 : new_r; - new_g = new_g > 1.0 ? 1.0 : new_g; - new_b = new_b > 1.0 ? 1.0 : new_b; - new_a = new_a > 1.0 ? 1.0 : new_a; - r_dst = Color(new_r, new_g, new_b, new_a); - } - return; - default: { - r_dst = c < 0.5 ? a : b; - } - return; - } -} - -void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &r_dst) { - if (a.type != b.type) { - if (a.is_num() && b.is_num()) { - //not as efficient but.. - real_t va = a; - real_t vb = b; - r_dst = va + (vb - va) * c; - - } else { - r_dst = a; - } - return; - } - - switch (a.type) { - case NIL: { - r_dst = Variant(); - } - return; - case BOOL: { - r_dst = a; - } - return; - case INT: { - int64_t va = a._data._int; - int64_t vb = b._data._int; - r_dst = int(va + (vb - va) * c); - } - return; - case FLOAT: { - real_t va = a._data._float; - real_t vb = b._data._float; - r_dst = va + (vb - va) * c; - } - return; - case STRING: { - //this is pretty funny and bizarre, but artists like to use it for typewritter effects - String sa = *reinterpret_cast<const String *>(a._data._mem); - String sb = *reinterpret_cast<const String *>(b._data._mem); - String dst; - int sa_len = sa.length(); - int sb_len = sb.length(); - int csize = sa_len + (sb_len - sa_len) * c; - if (csize == 0) { - r_dst = ""; - return; - } - dst.resize(csize + 1); - dst[csize] = 0; - int split = csize / 2; - - for (int i = 0; i < csize; i++) { - char32_t chr = ' '; - - if (i < split) { - if (i < sa.length()) { - chr = sa[i]; - } else if (i < sb.length()) { - chr = sb[i]; - } - - } else { - if (i < sb.length()) { - chr = sb[i]; - } else if (i < sa.length()) { - chr = sa[i]; - } - } - - dst[i] = chr; - } - - r_dst = dst; - } - return; - case VECTOR2: { - r_dst = reinterpret_cast<const Vector2 *>(a._data._mem)->lerp(*reinterpret_cast<const Vector2 *>(b._data._mem), c); - } - return; - case VECTOR2I: { - int32_t vax = reinterpret_cast<const Vector2i *>(a._data._mem)->x; - int32_t vbx = reinterpret_cast<const Vector2i *>(b._data._mem)->x; - int32_t vay = reinterpret_cast<const Vector2i *>(a._data._mem)->y; - int32_t vby = reinterpret_cast<const Vector2i *>(b._data._mem)->y; - r_dst = Vector2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5)); - } - return; - - case RECT2: { - r_dst = Rect2(reinterpret_cast<const Rect2 *>(a._data._mem)->position.lerp(reinterpret_cast<const Rect2 *>(b._data._mem)->position, c), reinterpret_cast<const Rect2 *>(a._data._mem)->size.lerp(reinterpret_cast<const Rect2 *>(b._data._mem)->size, c)); - } - return; - case RECT2I: { - const Rect2i *ra = reinterpret_cast<const Rect2i *>(a._data._mem); - const Rect2i *rb = reinterpret_cast<const Rect2i *>(b._data._mem); - - int32_t vax = ra->position.x; - int32_t vay = ra->position.y; - int32_t vbx = ra->size.x; - int32_t vby = ra->size.y; - int32_t vcx = rb->position.x; - int32_t vcy = rb->position.y; - int32_t vdx = rb->size.x; - int32_t vdy = rb->size.y; - - r_dst = Rect2i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vcx + vdx * c + 0.5), int32_t(vcy + vdy * c + 0.5)); - } - return; - - case VECTOR3: { - r_dst = reinterpret_cast<const Vector3 *>(a._data._mem)->lerp(*reinterpret_cast<const Vector3 *>(b._data._mem), c); - } - return; - case VECTOR3I: { - int32_t vax = reinterpret_cast<const Vector3i *>(a._data._mem)->x; - int32_t vbx = reinterpret_cast<const Vector3i *>(b._data._mem)->x; - int32_t vay = reinterpret_cast<const Vector3i *>(a._data._mem)->y; - int32_t vby = reinterpret_cast<const Vector3i *>(b._data._mem)->y; - int32_t vaz = reinterpret_cast<const Vector3i *>(a._data._mem)->z; - int32_t vbz = reinterpret_cast<const Vector3i *>(b._data._mem)->z; - r_dst = Vector3i(int32_t(vax + vbx * c + 0.5), int32_t(vay + vby * c + 0.5), int32_t(vaz + vbz * c + 0.5)); - } - return; - - case TRANSFORM2D: { - r_dst = a._data._transform2d->interpolate_with(*b._data._transform2d, c); - } - return; - case PLANE: { - r_dst = a; - } - return; - case QUAT: { - r_dst = reinterpret_cast<const Quat *>(a._data._mem)->slerp(*reinterpret_cast<const Quat *>(b._data._mem), c); - } - return; - case AABB: { - r_dst = ::AABB(a._data._aabb->position.lerp(b._data._aabb->position, c), a._data._aabb->size.lerp(b._data._aabb->size, c)); - } - return; - case BASIS: { - r_dst = Transform(*a._data._basis).interpolate_with(Transform(*b._data._basis), c).basis; - } - return; - case TRANSFORM: { - r_dst = a._data._transform->interpolate_with(*b._data._transform, c); - } - return; - case COLOR: { - r_dst = reinterpret_cast<const Color *>(a._data._mem)->lerp(*reinterpret_cast<const Color *>(b._data._mem), c); - } - return; - case STRING_NAME: { - r_dst = a; - } - return; - case NODE_PATH: { - r_dst = a; - } - return; - case _RID: { - r_dst = a; - } - return; - case OBJECT: { - r_dst = a; - } - return; - case DICTIONARY: { - } - return; - case ARRAY: { - r_dst = a; - } - return; - case PACKED_BYTE_ARRAY: { - r_dst = a; - } - return; - case PACKED_INT32_ARRAY: { - const Vector<int32_t> *arr_a = &PackedArrayRef<int32_t>::get_array(a._data.packed_array); - const Vector<int32_t> *arr_b = &PackedArrayRef<int32_t>::get_array(b._data.packed_array); - int32_t sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { - r_dst = a; - } else { - Vector<int32_t> v; - v.resize(sz); - { - int32_t *vw = v.ptrw(); - const int32_t *ar = arr_a->ptr(); - const int32_t *br = arr_b->ptr(); - - Variant va; - for (int32_t i = 0; i < sz; i++) { - Variant::interpolate(ar[i], br[i], c, va); - vw[i] = va; - } - } - r_dst = v; - } - } - return; - case PACKED_INT64_ARRAY: { - const Vector<int64_t> *arr_a = &PackedArrayRef<int64_t>::get_array(a._data.packed_array); - const Vector<int64_t> *arr_b = &PackedArrayRef<int64_t>::get_array(b._data.packed_array); - int64_t sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { - r_dst = a; - } else { - Vector<int64_t> v; - v.resize(sz); - { - int64_t *vw = v.ptrw(); - const int64_t *ar = arr_a->ptr(); - const int64_t *br = arr_b->ptr(); - - Variant va; - for (int64_t i = 0; i < sz; i++) { - Variant::interpolate(ar[i], br[i], c, va); - vw[i] = va; - } - } - r_dst = v; - } - } - return; - case PACKED_FLOAT32_ARRAY: { - const Vector<float> *arr_a = &PackedArrayRef<float>::get_array(a._data.packed_array); - const Vector<float> *arr_b = &PackedArrayRef<float>::get_array(b._data.packed_array); - int sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { - r_dst = a; - } else { - Vector<float> v; - v.resize(sz); - { - float *vw = v.ptrw(); - const float *ar = arr_a->ptr(); - const float *br = arr_b->ptr(); - - Variant va; - for (int i = 0; i < sz; i++) { - Variant::interpolate(ar[i], br[i], c, va); - vw[i] = va; - } - } - r_dst = v; - } - } - return; - case PACKED_FLOAT64_ARRAY: { - const Vector<double> *arr_a = &PackedArrayRef<double>::get_array(a._data.packed_array); - const Vector<double> *arr_b = &PackedArrayRef<double>::get_array(b._data.packed_array); - int sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { - r_dst = a; - } else { - Vector<double> v; - v.resize(sz); - { - double *vw = v.ptrw(); - const double *ar = arr_a->ptr(); - const double *br = arr_b->ptr(); - - Variant va; - for (int i = 0; i < sz; i++) { - Variant::interpolate(ar[i], br[i], c, va); - vw[i] = va; - } - } - r_dst = v; - } - } - return; - case PACKED_STRING_ARRAY: { - r_dst = a; - } - return; - case PACKED_VECTOR2_ARRAY: { - const Vector<Vector2> *arr_a = &PackedArrayRef<Vector2>::get_array(a._data.packed_array); - const Vector<Vector2> *arr_b = &PackedArrayRef<Vector2>::get_array(b._data.packed_array); - int sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { - r_dst = a; - } else { - Vector<Vector2> v; - v.resize(sz); - { - Vector2 *vw = v.ptrw(); - const Vector2 *ar = arr_a->ptr(); - const Vector2 *br = arr_b->ptr(); - - for (int i = 0; i < sz; i++) { - vw[i] = ar[i].lerp(br[i], c); - } - } - r_dst = v; - } - } - return; - case PACKED_VECTOR3_ARRAY: { - const Vector<Vector3> *arr_a = &PackedArrayRef<Vector3>::get_array(a._data.packed_array); - const Vector<Vector3> *arr_b = &PackedArrayRef<Vector3>::get_array(b._data.packed_array); - int sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { - r_dst = a; - } else { - Vector<Vector3> v; - v.resize(sz); - { - Vector3 *vw = v.ptrw(); - const Vector3 *ar = arr_a->ptr(); - const Vector3 *br = arr_b->ptr(); - - for (int i = 0; i < sz; i++) { - vw[i] = ar[i].lerp(br[i], c); - } - } - r_dst = v; - } - } - return; - case PACKED_COLOR_ARRAY: { - const Vector<Color> *arr_a = &PackedArrayRef<Color>::get_array(a._data.packed_array); - const Vector<Color> *arr_b = &PackedArrayRef<Color>::get_array(b._data.packed_array); - int sz = arr_a->size(); - if (sz == 0 || arr_b->size() != sz) { - r_dst = a; - } else { - Vector<Color> v; - v.resize(sz); - { - Color *vw = v.ptrw(); - const Color *ar = arr_a->ptr(); - const Color *br = arr_b->ptr(); - - for (int i = 0; i < sz; i++) { - vw[i] = ar[i].lerp(br[i], c); - } - } - r_dst = v; - } - } - return; - default: { - r_dst = a; - } - } -} - -static const char *_op_names[Variant::OP_MAX] = { - "==", - "!=", - "<", - "<=", - ">", - ">=", - "+", - "-", - "*", - "/", - "- (negation)", - "+ (positive)", - "%", - "+ (concatenation)", - "<<", - ">>", - "&", - "|", - "^", - "~", - "and", - "or", - "xor", - "not", - "in" - -}; - -String Variant::get_operator_name(Operator p_op) { - ERR_FAIL_INDEX_V(p_op, OP_MAX, ""); - return _op_names[p_op]; -} diff --git a/core/version.h b/core/version.h index 1198f62db4..2a4fa9cfd4 100644 --- a/core/version.h +++ b/core/version.h @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ |