diff --git a/.github/actions/godot-cache-restore/action.yml b/.github/actions/godot-cache-restore/action.yml index 5df577656..e38df0bb6 100644 --- a/.github/actions/godot-cache-restore/action.yml +++ b/.github/actions/godot-cache-restore/action.yml @@ -5,17 +5,18 @@ inputs: description: The cache base name (job name by default). default: "${{github.job}}" scons-cache: - description: The scons cache path. + description: The SCons cache path. default: "${{github.workspace}}/.scons-cache/" runs: - using: "composite" + using: composite steps: - - name: Restore .scons_cache directory - uses: actions/cache/restore@v3 + - name: Restore SCons cache directory + uses: actions/cache/restore@v4 with: path: ${{inputs.scons-cache}} - key: ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} + key: ${{inputs.cache-name}}-${{env.BLAZIUM_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} restore-keys: | - ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} - ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}} - ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}} + ${{inputs.cache-name}}-${{env.BLAZIUM_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} + ${{inputs.cache-name}}-${{env.BLAZIUM_BASE_BRANCH}}-${{github.ref}} + ${{inputs.cache-name}}-${{env.BLAZIUM_BASE_BRANCH}}-refs/heads/${{env.BLAZIUM_BASE_BRANCH}} + ${{inputs.cache-name}}-${{env.BLAZIUM_BASE_BRANCH}} diff --git a/.github/actions/godot-cache-save/action.yml b/.github/actions/godot-cache-save/action.yml index b7cbf91f9..061da6a25 100644 --- a/.github/actions/godot-cache-save/action.yml +++ b/.github/actions/godot-cache-save/action.yml @@ -8,10 +8,10 @@ inputs: description: The SCons cache path. default: "${{github.workspace}}/.scons-cache/" runs: - using: "composite" + using: composite steps: - name: Save SCons cache directory uses: actions/cache/save@v4 with: path: ${{inputs.scons-cache}} - key: ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} + key: ${{inputs.cache-name}}-${{env.BLAZIUM_BASE_BRANCH}}-${{github.ref}}-${{github.sha}} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13b7243e0..75d94835d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,11 +1,17 @@ name: Continuous integration -on: [push, pull_request] + +on: + push: + pull_request: env: # Only used for the cache key. Increment version to force clean build. - GODOT_BASE_BRANCH: master + BLAZIUM_BASE_BRANCH: blazium-dev # Used to select the version of Godot to run the tests with. - GODOT_TEST_VERSION: master + BLAZIUM_TEST_VERSION: 0.1.184 + # Use UTF-8 on Linux. + LANG: en_US.UTF-8 + LC_ALL: en_US.UTF-8 concurrency: group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}} @@ -91,7 +97,6 @@ jobs: env: SCONS_CACHE: ${{ github.workspace }}/.scons-cache/ EM_VERSION: 3.1.39 - EM_CACHE_FOLDER: "emsdk-cache" steps: - name: Checkout @@ -108,10 +113,10 @@ jobs: - name: Set up Python (for SCons) uses: actions/setup-python@v5 with: - python-version: '3.x' + python-version: 3.x - name: Android dependencies - if: ${{ matrix.platform == 'android' }} + if: matrix.platform == 'android' uses: nttld/setup-ndk@v1 with: ndk-version: r23c @@ -122,7 +127,7 @@ jobs: uses: mymindstorm/setup-emsdk@v14 with: version: ${{env.EM_VERSION}} - actions-cache-folder: ${{env.EM_CACHE_FOLDER}} + no-cache: true - name: Setup MinGW for Windows/MinGW build if: ${{ matrix.platform == 'windows' && matrix.flags == 'use_mingw=yes' }} @@ -161,10 +166,10 @@ jobs: - name: Download latest Godot artifacts uses: dsnopek/action-download-artifact@1322f74e2dac9feed2ee76a32d9ae1ca3b4cf4e9 - if: ${{ matrix.run-tests && env.GODOT_TEST_VERSION == 'master' }} + if: matrix.run-tests && env.BLAZIUM_TEST_VERSION == 'blazium-dev' with: - repo: godotengine/godot - branch: master + repo: blazium-engine/blazium + branch: blazium-dev event: push workflow: linux_builds.yml workflow_conclusion: success @@ -175,59 +180,35 @@ jobs: path: godot-artifacts - name: Prepare Godot artifacts for testing - if: ${{ matrix.run-tests && env.GODOT_TEST_VERSION == 'master' }} + if: matrix.run-tests && env.BLAZIUM_TEST_VERSION == 'blazium-dev' run: | chmod +x ./godot-artifacts/godot.linuxbsd.editor.x86_64.mono - echo "GODOT=$(pwd)/godot-artifacts/godot.linuxbsd.editor.x86_64.mono" >> $GITHUB_ENV + echo "BLAZIUM=$(pwd)/godot-artifacts/godot.linuxbsd.editor.x86_64.mono" >> $GITHUB_ENV - name: Download requested Godot version for testing - if: ${{ matrix.run-tests && env.GODOT_TEST_VERSION != 'master' }} + if: matrix.run-tests && env.BLAZIUM_TEST_VERSION != 'blazium-dev' run: | - wget "https://github.com/godotengine/godot-builds/releases/download/${GODOT_TEST_VERSION}/Godot_v${GODOT_TEST_VERSION}_linux.x86_64.zip" -O Godot.zip - unzip -a Godot.zip - chmod +x "Godot_v${GODOT_TEST_VERSION}_linux.x86_64" - echo "GODOT=$(pwd)/Godot_v${GODOT_TEST_VERSION}_linux.x86_64" >> $GITHUB_ENV + wget "https://cdn.blazium.app/nightly/${BLAZIUM_TEST_VERSION}/BlaziumEditor_v${BLAZIUM_TEST_VERSION}_linux.x86_64.zip" -O Blazium.zip + unzip -a Blazium.zip + chmod +x "BlaziumEditor_v${BLAZIUM_TEST_VERSION}_linux.x86_64" + echo "BLAZIUM=$(pwd)/BlaziumEditor_v${BLAZIUM_TEST_VERSION}_linux.x86_64" >> $GITHUB_ENV - name: Run tests - if: ${{ matrix.run-tests }} + if: matrix.run-tests run: | - $GODOT --headless --version + $BLAZIUM --headless --version cd test # Need to run the editor so .godot is generated... but it crashes! Ignore that :-) - (cd project && (timeout 30 $GODOT --import --headless >/dev/null 2>&1 || true)) + (cd project && (timeout 30 $BLAZIUM --import --headless >/dev/null 2>&1 || true)) ./run-tests.sh - name: Upload artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.artifact-name }} path: ${{ matrix.artifact-path }} if-no-files-found: error - linux-cmake: - name: 🐧 Build (Linux, GCC, CMake) - runs-on: ubuntu-20.04 - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Install dependencies - run: | - sudo apt-get update -qq - sudo apt-get install -qqq build-essential pkg-config cmake - - - name: Build godot-cpp - run: | - cmake -DCMAKE_BUILD_TYPE=Release . - make -j $(nproc) VERBOSE=1 - - - name: Build test GDExtension library - run: | - cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." . - make -j $(nproc) VERBOSE=1 - linux-cmake-ninja: name: 🐧 Build (Linux, GCC, CMake Ninja) runs-on: ubuntu-20.04 @@ -242,15 +223,12 @@ jobs: sudo apt-get update -qq sudo apt-get install -qqq build-essential pkg-config cmake ninja-build - - name: Build godot-cpp - run: | - cmake -DCMAKE_BUILD_TYPE=Release -GNinja . - cmake --build . -j $(nproc) --verbose - - name: Build test GDExtension library run: | - cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -GNinja . - cmake --build . -j $(nproc) --verbose + mkdir cmake-build + cd cmake-build + cmake ../ -DTEST_TARGET=template_release + cmake --build . --verbose -j $(nproc) -t godot-cpp-test --config Release windows-msvc-cmake: name: 🏁 Build (Windows, MSVC, CMake) @@ -261,12 +239,9 @@ jobs: with: submodules: recursive - - name: Build godot-cpp - run: | - cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 16 2019" . - cmake --build . --verbose --config Release - - name: Build test GDExtension library run: | - cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -G"Visual Studio 16 2019" . - cmake --build . --verbose --config Release + mkdir cmake-build + cd cmake-build + cmake ../ -DTEST_TARGET=template_release + cmake --build . --verbose -t godot-cpp-test --config Release diff --git a/.github/workflows/runner.yml b/.github/workflows/runner.yml new file mode 100644 index 000000000..66357b50e --- /dev/null +++ b/.github/workflows/runner.yml @@ -0,0 +1,25 @@ +name: 🔗 GHA + +on: + push: + pull_request: + merge_group: + +concurrency: + group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-runner + cancel-in-progress: true + +jobs: + # First stage: Only static checks, fast and prevent expensive builds from running. + + static-checks: + if: '!vars.DISABLE_GODOT_CI' + name: 📊 Static Checks + uses: ./.github/workflows/static_checks.yml + + # Second stage: Run all the builds and some of the tests. + + ci: + name: 🛠️ Continuous Integration + needs: static-checks + uses: ./.github/workflows/ci.yml diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml index 6899248ea..429b162d9 100644 --- a/.github/workflows/static_checks.yml +++ b/.github/workflows/static_checks.yml @@ -1,5 +1,8 @@ name: 📊 Static Checks -on: [push, pull_request] + +on: + push: + pull_request: concurrency: group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-static diff --git a/.gitignore b/.gitignore index ee9a3f756..9bb08ed34 100644 --- a/.gitignore +++ b/.gitignore @@ -198,4 +198,7 @@ venv # Clion Configuration .idea/ -cmake-build-* +cmake-build*/ + +# CMake related +CMakeUserPresets.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e63f1d40c..49956fc1e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,13 @@ repos: language: python entry: python misc/scripts/copyright_headers.py files: \.(c|h)pp$ + exclude: | + (?x)^( + test/.*| + include/godot_cpp/variant/ok_color.hpp + ) exclude: ^test/ + - id: header-guards name: header-guards diff --git a/CMakeLists.txt b/CMakeLists.txt index ff77368ba..208fae82b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,24 +1,98 @@ -cmake_minimum_required(VERSION 3.13) -project(godot-cpp LANGUAGES CXX) - -# Configure CMake -# https://discourse.cmake.org/t/how-do-i-remove-compile-options-from-target/5965 -# https://stackoverflow.com/questions/74426638/how-to-remove-rtc1-from-specific-target-or-file-in-cmake -if(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC) - if(NOT CMAKE_BUILD_TYPE MATCHES Debug) - STRING(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) - endif () -endif () +cmake_minimum_required(VERSION 3.17) + +#[=======================================================================[.rst: + +CMake Version requirements +-------------------------- + +To enable use of the emscripten emsdk hack for pseudo shared library support +without polluting options for consumers we need to use the +CMAKE_PROJECT__INCLUDE which was introduced in version 3.17 + +Scons Compatibility +------------------- + +As we are attempting to maintain feature parity, and ease of maintenance, these +CMake scripts are built to resemble the SCons build system. -include( ${PROJECT_SOURCE_DIR}/cmake/godotcpp.cmake ) +The file structure and file content are made to match, if not in content then +in spirit. The closer the two build systems look the easier they will be to +maintain. -# I know this doesn't look like a typical CMakeLists.txt, but as we are -# attempting mostly feature parity with SCons, and easy maintenance, the closer -# the two build systems look the easier they will be to keep in lockstep. +Where the SCons additional scripts in the tools directory, The CMake scripts +are in the cmake directory. -# The typical target definitions are in ${PROJECT_SOURCE_DIR}/cmake/godotcpp.cmake +For example, the tools/godotcpp.py is sourced into SCons, and the 'options' +function is run. +.. highlight:: python + + cpp_tool = Tool("godotcpp", toolpath=["tools"]) + cpp_tool.options(opts, env) + + +The CMake equivalent is below. +]=======================================================================] + +include( cmake/godotcpp.cmake ) godotcpp_options() +#[=======================================================================[.rst: + +Configurations +-------------- + +There are two build main configurations, 'Debug' and 'Release', these are not +related to godot's DEBUG_FEATURES flag. Build configurations change the default +compiler and linker flags present when building the library, things like debug +symbols, optimization. + +The Scons build scripts don't have this concept, you can think of it like the +SCons solution has a single default configuration. In both cases overriding the +defaults is controlled by options on the command line, or in preset files. + +Because of this added configuration and that it can be undefined, it becomes +important to set a default, considering the SCons solution that does not enable +debug symbols by default, it seemed appropriate to set the default to 'Release' +if unspecified. This can always be overridden like below. + +.. highlight:: shell + + cmake -DCMAKE_BUILD_TYPE:STRING=Debug + +.. caution:: + +A complication arises from `Multi-Config Generators`_ that cannot have +their configuration set at configure time. This means that the configuration +must be set on the build command. This is especially important for Visual +Studio Generators which default to 'Debug' + +.. highlight:: shell + + cmake --build . --config Release + +.. _Multi-Config Generators:https://cmake.org/cmake/help/latest/prop_gbl/GENERATOR_IS_MULTI_CONFIG.html +]=======================================================================] +get_property( IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG ) +if( NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE ) + if( GODOT_DEV_BUILD ) + set( CMAKE_BUILD_TYPE Debug ) + else () + set( CMAKE_BUILD_TYPE Release ) + endif () +endif () + +#[[ Python is required for code generation ]] +find_package(Python3 3.4 REQUIRED) # pathlib should be present + +# Define our project. +project( godot-cpp + VERSION 4.3 + DESCRIPTION "C++ bindings for the Godot Engine's GDExtensions API." + HOMEPAGE_URL "https://github.com/blazium-engine/godot-cpp" + LANGUAGES CXX) + godotcpp_generate() + +# Test Example +add_subdirectory( test ) diff --git a/binding_generator.py b/binding_generator.py index 75e56fde1..71afe047e 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -542,8 +542,14 @@ def generate_builtin_bindings(api, output_dir, build_config): builtin_header.append("") + includes = [] for builtin in builtin_classes: - builtin_header.append(f"#include ") + includes.append(f"godot_cpp/variant/{camel_to_snake(builtin)}.hpp") + + includes.sort() + + for include in includes: + builtin_header.append(f"#include <{include}>") builtin_header.append("") @@ -599,11 +605,10 @@ def generate_builtin_class_vararg_method_implements_header(builtin_classes): continue result += make_varargs_template( - method, "is_static" in method and method["is_static"], class_name, False, False, True + method, "is_static" in method and method["is_static"], class_name, False, True ) result.append("") - result.append("") result.append(f"#endif // ! {header_guard}") return "\n".join(result) @@ -628,38 +633,53 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl # Special cases. if class_name == "String": + result.append("#include ") result.append("#include ") result.append("#include ") - result.append("#include ") + result.append("") if class_name == "PackedStringArray": result.append("#include ") + result.append("") if class_name == "PackedColorArray": result.append("#include ") + result.append("") if class_name == "PackedVector2Array": result.append("#include ") + result.append("") if class_name == "PackedVector3Array": result.append("#include ") + result.append("") if class_name == "PackedVector4Array": result.append("#include ") + result.append("") if is_packed_array(class_name): result.append("#include ") result.append("#include ") + result.append("") if class_name == "Array": result.append("#include ") + result.append("") if class_name == "Callable": result.append("#include ") - - for include in fully_used_classes: - if include == "TypedArray": - result.append("#include ") - else: - result.append(f"#include ") + result.append("") if len(fully_used_classes) > 0: + includes = [] + for include in fully_used_classes: + if include == "TypedArray": + includes.append("godot_cpp/variant/typed_array.hpp") + else: + includes.append(f"godot_cpp/{get_include_path(include)}") + + includes.sort() + + for include in includes: + result.append(f"#include <{include}>") + result.append("") result.append("#include ") @@ -737,7 +757,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("public:") result.append( - f"\t_FORCE_INLINE_ GDExtensionTypePtr _native_ptr() const {{ return const_cast(&opaque); }}" + f"\t_FORCE_INLINE_ GDExtensionTypePtr _native_ptr() const {{ return const_cast(&opaque); }}" ) copy_constructor_index = -1 @@ -918,7 +938,7 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append(f"\tconst {return_type} *ptr() const;") result.append(f"\t{return_type} *ptrw();") iterators = """ - struct Iterator { + struct Iterator { _FORCE_INLINE_ $TYPE &operator*() const { return *elem_ptr; } @@ -980,19 +1000,17 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl } _FORCE_INLINE_ ConstIterator end() const { return ConstIterator(ptr() + size()); - } -""" + }""" result.append(iterators.replace("$TYPE", return_type)) init_list = """ - _FORCE_INLINE_ $CLASS(std::initializer_list<$TYPE> p_init) { + _FORCE_INLINE_ $CLASS(std::initializer_list<$TYPE> p_init) { ERR_FAIL_COND(resize(p_init.size()) != 0); size_t i = 0; for (const $TYPE &element : p_init) { set(i++, element); } - } -""" + }""" result.append(init_list.replace("$TYPE", return_type).replace("$CLASS", class_name)) if class_name == "Array": @@ -1031,7 +1049,9 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("") result.append("} // namespace godot") + result.append("") result.append(f"#endif // ! {header_guard}") + result.append("") return "\n".join(result) @@ -1045,7 +1065,6 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl add_header(f"{snake_class_name}.cpp", result) - result.append("") result.append(f"#include ") result.append("") result.append("#include ") @@ -1054,10 +1073,16 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl result.append("") # Only used since the "fully used" is included in header already. - for include in used_classes: - result.append(f"#include ") - if len(used_classes) > 0: + includes = [] + for included in used_classes: + includes.append(f"godot_cpp/{get_include_path(included)}") + + includes.sort() + + for included in includes: + result.append(f"#include <{included}>") + result.append("") result.append("#include ") @@ -1307,7 +1332,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl f'{correct_type(operator["return_type"])} {class_name}::operator{get_operator_cpp_name(operator["name"])}() const {{' ) result.append( - f'\treturn internal::_call_builtin_operator_ptr<{get_gdextension_type(correct_type(operator["return_type"]))}>(_method_bindings.operator_{get_operator_id_name(operator["name"])}, (GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr)nullptr);' + f'\treturn internal::_call_builtin_operator_ptr<{get_gdextension_type(correct_type(operator["return_type"]))}>(_method_bindings.operator_{get_operator_id_name(operator["name"])}, (GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr) nullptr);' ) result.append("}") result.append("") @@ -1343,6 +1368,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl result.append("") result.append("} //namespace godot") + result.append("") return "\n".join(result) @@ -1518,11 +1544,18 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node): result.append("") - for included in used_classes: - result.append(f"#include ") + if len(used_classes) > 0: + includes = [] + for included in used_classes: + includes.append(f"godot_cpp/{get_include_path(included)}") - if len(used_classes) == 0: + includes.sort() + + for include in includes: + result.append(f"#include <{include}>") + else: result.append("#include ") + result.append("") result.append("namespace godot {") @@ -1562,16 +1595,23 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append("") - for included in fully_used_classes: - if included == "TypedArray": - result.append("#include ") - else: - result.append(f"#include ") + if len(fully_used_classes) > 0: + includes = [] + for included in fully_used_classes: + if included == "TypedArray": + includes.append("godot_cpp/variant/typed_array.hpp") + else: + includes.append(f"godot_cpp/{get_include_path(included)}") + + includes.sort() + + for include in includes: + result.append(f"#include <{include}>") + + result.append("") if class_name == "EditorPlugin": result.append("#include ") - - if len(fully_used_classes) > 0: result.append("") if class_name != "Object" and class_name != "ClassDBSingleton": @@ -1610,7 +1650,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append("") result.append("public:") - result.append("") if "enums" in class_api: for enum_api in class_api["enums"]: @@ -1643,6 +1682,10 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us vararg = "is_vararg" in method and method["is_vararg"] + if vararg: + result.append("") + result.append("private:") + method_signature = "\t" method_signature += make_signature( class_name, method, for_header=True, use_template_get_node=use_template_get_node @@ -1650,6 +1693,8 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append(method_signature + ";") if vararg: + result.append("") + result.append("public:") # Add templated version. result += make_varargs_template(method) @@ -1664,6 +1709,8 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us ) result.append(method_signature + ";") + result.append("") + result.append("protected:") # T is the custom class we want to register (from which the call initiates, going up the inheritance chain), # B is its base class (can be a custom class too, that's why we pass it). @@ -1680,7 +1727,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us # If the method is different from the base class, it means T overrides it, so it needs to be bound. # Note that with an `if constexpr`, the code inside the `if` will not even be compiled if the # condition returns false (in such cases it can't compile due to ambiguity). - f"\t\tif constexpr (!std::is_same_v) {{" + f"\t\tif constexpr (!std::is_same_v) {{" ) result.append(f"\t\t\tBIND_VIRTUAL_METHOD(T, {method_name});") result.append("\t\t}") @@ -1708,7 +1755,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us if class_name == "WorkerThreadPool": result.append("\tenum {") - result.append("\tINVALID_TASK_ID = -1") + result.append("\t\tINVALID_TASK_ID = -1") result.append("\t};") result.append("\ttypedef int64_t TaskID;") result.append("\ttypedef int64_t GroupID;") @@ -1720,8 +1767,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us ) if class_name == "Object": - result.append("") - result.append("\ttemplate ") result.append("\tstatic T *cast_to(Object *p_object);") @@ -1736,7 +1781,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us "\tT *get_node(const NodePath &p_path) const { return Object::cast_to(get_node_internal(p_path)); }" ) - result.append("") result.append("};") result.append("") @@ -1820,7 +1864,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append(method_body) result.append("\t} \\") - result.append("\t;") + result.append("\t") result.append("") result.append("#define CLASSDB_SINGLETON_VARIANT_CAST \\") @@ -1832,10 +1876,11 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us else: result.append(f'\tVARIANT_ENUM_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\') - result.append("\t;") + result.append("\t") result.append("") result.append(f"#endif // ! {header_guard}") + result.append("") return "\n".join(result) @@ -1857,10 +1902,16 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result.append("#include ") result.append("") - for included in used_classes: - result.append(f"#include ") - if len(used_classes) > 0: + includes = [] + for included in used_classes: + includes.append(f"godot_cpp/{get_include_path(included)}") + + includes.sort() + + for included in includes: + result.append(f"#include <{included}>") + result.append("") result.append("namespace godot {") @@ -2010,8 +2061,8 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result.append(method_signature) result.append("") + result.append("} // namespace godot") result.append("") - result.append("} // namespace godot ") return "\n".join(result) @@ -2039,23 +2090,24 @@ def generate_global_constants(api, output_dir): header.append("namespace godot {") header.append("") - for constant in api["global_constants"]: - header.append(f'\tconst int64_t {escape_identifier(constant["name"])} = {constant["value"]};') + if len(api["global_constants"]) > 0: + for constant in api["global_constants"]: + header.append(f'const int64_t {escape_identifier(constant["name"])} = {constant["value"]};') - header.append("") + header.append("") for enum_def in api["global_enums"]: if enum_def["name"].startswith("Variant."): continue if enum_def["is_bitfield"]: - header.append(f'\tenum {enum_def["name"]} : uint64_t {{') + header.append(f'enum {enum_def["name"]} : uint64_t {{') else: - header.append(f'\tenum {enum_def["name"]} {{') + header.append(f'enum {enum_def["name"]} {{') for value in enum_def["values"]: - header.append(f'\t\t{value["name"]} = {value["value"]},') - header.append("\t};") + header.append(f'\t{value["name"]} = {value["value"]},') + header.append("};") header.append("") header.append("} // namespace godot") @@ -2166,13 +2218,25 @@ def generate_utility_functions(api, output_dir): header.append("public:") for function in api["utility_functions"]: + if function["name"] == "is_instance_valid": + # The `is_instance_valid()` function doesn't work as developers expect, and unless used very + # carefully will cause crashes. Instead, developers should use `ObjectDB::get_instance()` + # with object ids to ensure that an instance is still valid. + continue + vararg = "is_vararg" in function and function["is_vararg"] + if vararg: + header.append("") + header.append("private:") + function_signature = "\t" function_signature += make_signature("UtilityFunctions", function, for_header=True, static=True) header.append(function_signature + ";") if vararg: + header.append("") + header.append("public:") # Add templated version. header += make_varargs_template(function, static=True) @@ -2193,13 +2257,16 @@ def generate_utility_functions(api, output_dir): source.append("#include ") source.append("") - source.append("#include ") source.append("#include ") + source.append("#include ") source.append("") source.append("namespace godot {") source.append("") for function in api["utility_functions"]: + if function["name"] == "is_instance_valid": + continue + vararg = "is_vararg" in function and function["is_vararg"] function_signature = make_signature("UtilityFunctions", function) @@ -2293,7 +2360,7 @@ def make_function_parameters(parameters, include_default=False, for_builtin=Fals signature.append(parameter) if is_vararg: - signature.append("const Args&... p_args") + signature.append("const Args &...p_args") return ", ".join(signature) @@ -2351,9 +2418,6 @@ def make_signature( if "is_virtual" in function_data and function_data["is_virtual"]: function_signature += "virtual " - if is_vararg: - function_signature += "private: " - if static: function_signature += "static " @@ -2406,7 +2470,6 @@ def make_varargs_template( function_data, static=False, class_befor_signature="", - with_public_declare=True, with_indent=True, for_builtin_classes=False, ): @@ -2414,10 +2477,7 @@ def make_varargs_template( function_signature = "" - if with_public_declare: - function_signature = "public: " - - function_signature += "template " + result.append("template ") if static: function_signature += "static " @@ -2460,7 +2520,7 @@ def make_varargs_template( function_signature += " {" result.append(function_signature) - args_array = f"\tstd::array variant_args {{ " + args_array = f"\tstd::array variant_args{{ " for argument in method_arguments: if argument["type"] == "Variant": args_array += escape_argument(argument["name"]) diff --git a/cmake/android.cmake b/cmake/android.cmake new file mode 100644 index 000000000..2227f89ce --- /dev/null +++ b/cmake/android.cmake @@ -0,0 +1,41 @@ +#[=======================================================================[.rst: +Android +------- + +This file contains functions for options and configuration for targeting the +Android platform + +Configuration of the Android toolchain is done using toolchain files, +CMakePresets, or variables on the command line. + +The `Android SDK`_ provides toolchain files to help with configuration. + +CMake has its own `built-in support`_ for cross compiling to the +Android platforms. + +.. warning:: + + Android does not support or test the CMake built-in workflow, recommend + using their toolchain file. + +.. _Android SDK:https://developer.android.com/ndk/guides/cmake + +.. _built-in support:https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android + +There is further information and examples in the doc/cmake.rst file. + +]=======================================================================] +function( android_options ) + # Android Options +endfunction() + +function( android_generate TARGET_NAME ) + + target_compile_definitions(${TARGET_NAME} + PUBLIC + ANDROID_ENABLED + UNIX_ENABLED + ) + + common_compiler_flags( ${TARGET_NAME} ) +endfunction() diff --git a/cmake/common_compiler_flags.cmake b/cmake/common_compiler_flags.cmake index 94556415b..1b185fe2c 100644 --- a/cmake/common_compiler_flags.cmake +++ b/cmake/common_compiler_flags.cmake @@ -1,94 +1,162 @@ -# Add warnings based on compiler & version -# Set some helper variables for readability -set( compiler_less_than_v8 "$,8>" ) -set( compiler_greater_than_or_equal_v9 "$,9>" ) -set( compiler_greater_than_or_equal_v11 "$,11>" ) -set( compiler_less_than_v11 "$,11>" ) -set( compiler_greater_than_or_equal_v12 "$,12>" ) - -# These compiler options reflect what is in godot/SConstruct. -target_compile_options( ${PROJECT_NAME} PRIVATE - # MSVC only - $<${compiler_is_msvc}: - /W4 - - # Disable warnings which we don't plan to fix. - /wd4100 # C4100 (unreferenced formal parameter): Doesn't play nice with polymorphism. - /wd4127 # C4127 (conditional expression is constant) - /wd4201 # C4201 (non-standard nameless struct/union): Only relevant for C89. - /wd4244 # C4244 C4245 C4267 (narrowing conversions): Unavoidable at this scale. - /wd4245 - /wd4267 - /wd4305 # C4305 (truncation): double to float or real_t, too hard to avoid. - /wd4514 # C4514 (unreferenced inline function has been removed) - /wd4714 # C4714 (function marked as __forceinline not inlined) - /wd4820 # C4820 (padding added after construct) - > - - # Clang and GNU common options - $<$: - -Wall - -Wctor-dtor-privacy - -Wextra - -Wno-unused-parameter - -Wnon-virtual-dtor - -Wwrite-strings - > - - # Clang only - $<${compiler_is_clang}: - -Wimplicit-fallthrough - -Wno-ordered-compare-function-pointers - > - - # GNU only - $<${compiler_is_gnu}: - -Walloc-zero - -Wduplicated-branches - -Wduplicated-cond - -Wno-misleading-indentation - -Wplacement-new=1 - -Wshadow-local - -Wstringop-overflow=4 - > - $<$: - # Bogus warning fixed in 8+. - -Wno-strict-overflow - > - $<$: - -Wattribute-alias=2 - > - $<$: - # Broke on MethodBind templates before GCC 11. - -Wlogical-op - > - $<$: - # Regression in GCC 9/10, spams so much in our variadic templates that we need to outright disable it. - -Wno-type-limits - > - $<$: - # False positives in our error macros, see GH-58747. - -Wno-return-type - > -) - -# Treat warnings as errors -function( set_warning_as_error ) - message( STATUS "[${PROJECT_NAME}] Treating warnings as errors") - if ( CMAKE_VERSION VERSION_GREATER_EQUAL "3.24" ) - set_target_properties( ${PROJECT_NAME} - PROPERTIES - COMPILE_WARNING_AS_ERROR ON - ) - else() - target_compile_options( ${PROJECT_NAME} - PRIVATE - $<${compiler_is_msvc}:/WX> - $<$:-Werror> - ) - endif() -endfunction() +#[=======================================================================[.rst: +Common Compiler Flags +--------------------- + +This file contains a single function to configure platform agnostic compiler +flags like optimization levels, warnings, and features. For platform specific +flags look to each of the ``cmake/.cmake`` files. + +]=======================================================================] +#Generator Expression Helpers +set( IS_CLANG "$" ) +set( IS_APPLECLANG "$" ) +set( IS_GNU "$" ) +set( IS_MSVC "$" ) +set( NOT_MSVC "$>" ) + +set( GNU_LT_V8 "$,8>" ) +set( GNU_GE_V9 "$,9>" ) +set( GNU_GT_V11 "$,11>" ) +set( GNU_LT_V11 "$,11>" ) +set( GNU_GE_V12 "$,12>" ) + +set( HOT_RELOAD-UNSET "$") + +set( DISABLE_EXCEPTIONS "$") + + +function( common_compiler_flags TARGET_NAME ) + set( IS_RELEASE "$") + set( DEBUG_FEATURES "$,$>" ) + set( HOT_RELOAD "$,$>" ) + set( DEBUG_SYMBOLS "$" ) + + target_compile_features(${TARGET_NAME} + PUBLIC + cxx_std_17 + ) + + # These compiler options reflect what is in godot/SConstruct. + target_compile_options( ${TARGET_NAME} + PUBLIC + # Disable exception handling. Godot doesn't use exceptions anywhere, and this + # saves around 20% of binary size and very significant build time. + $<${DISABLE_EXCEPTIONS}: + $<${NOT_MSVC}:-fno-exceptions> + > + $<$: + $<${IS_MSVC}:/EHsc> + > + + # Enabling Debug Symbols + $<${DEBUG_SYMBOLS}: + $<${IS_MSVC}: /Zi /FS> + + # Adding dwarf-4 explicitly makes stacktraces work with clang builds, + # otherwise addr2line doesn't understand them. + $<${NOT_MSVC}: + -gdwarf-4 + $ + > + > + + $<${IS_DEV}: + $<${NOT_MSVC}:-fno-omit-frame-pointer -O0 -g> + > + + $<${HOT_RELOAD}: + $<${IS_GNU}:-fno-gnu-unique> + > + + # MSVC only + $<${IS_MSVC}: + "/MP ${PROC_N}" + /W4 + + # Disable warnings which we don't plan to fix. + /wd4100 # C4100 (unreferenced formal parameter): Doesn't play nice with polymorphism. + /wd4127 # C4127 (conditional expression is constant) + /wd4201 # C4201 (non-standard nameless struct/union): Only relevant for C89. + /wd4244 # C4244 C4245 C4267 (narrowing conversions): Unavoidable at this scale. + /wd4245 + /wd4267 + /wd4305 # C4305 (truncation): double to float or real_t, too hard to avoid. + /wd4514 # C4514 (unreferenced inline function has been removed) + /wd4714 # C4714 (function marked as __forceinline not inlined) + /wd4820 # C4820 (padding added after construct) + + /utf-8 + > -if ( GODOT_WARNING_AS_ERROR ) - set_warning_as_error() -endif() + # Clang and GNU common options + $<$: + -Wall + -Wctor-dtor-privacy + -Wextra + -Wno-unused-parameter + -Wnon-virtual-dtor + -Wwrite-strings + > + + # Clang only + $<${IS_CLANG}: + -Wimplicit-fallthrough + -Wno-ordered-compare-function-pointers + > + + # GNU only + $<${IS_GNU}: + -Walloc-zero + -Wduplicated-branches + -Wduplicated-cond + -Wno-misleading-indentation + -Wplacement-new=1 + -Wshadow-local + -Wstringop-overflow=4 + + # Bogus warning fixed in 8+. + $<${GNU_LT_V8}:-Wno-strict-overflow> + + $<${GNU_GE_V9}:-Wattribute-alias=2> + + # Broke on MethodBind templates before GCC 11. + $<${GNU_GT_V11}:-Wlogical-op> + + # Regression in GCC 9/10, spams so much in our variadic templates that we need to outright disable it. + $<${GNU_LT_V11}:-Wno-type-limits> + + # False positives in our error macros, see GH-58747. + $<${GNU_GE_V12}:-Wno-return-type> + > + ) + + target_compile_definitions(${TARGET_NAME} + PUBLIC + GDEXTENSION + + # features + $<${DEBUG_FEATURES}:DEBUG_ENABLED DEBUG_METHODS_ENABLED> + + $<${HOT_RELOAD}:HOT_RELOAD_ENABLED> + + $<$:REAL_T_IS_DOUBLE> + + $<${IS_MSVC}:$<${DISABLE_EXCEPTIONS}:_HAS_EXCEPTIONS=0>> + ) + + target_link_options( ${TARGET_NAME} + PUBLIC + $<${IS_MSVC}: + /WX # treat link warnings as errors. + /MANIFEST:NO # We dont need a manifest + > + + $<${DEBUG_SYMBOLS}:$<${IS_MSVC}:/DEBUG:FULL>> + $<$: + $<${IS_GNU}:-s> + $<${IS_CLANG}:-s> + $<${IS_APPLECLANG}:-Wl,-S -Wl,-x -Wl,-dead_strip> + > + ) + +endfunction() diff --git a/cmake/emsdkHack.cmake b/cmake/emsdkHack.cmake new file mode 100644 index 000000000..6981a3796 --- /dev/null +++ b/cmake/emsdkHack.cmake @@ -0,0 +1,40 @@ +#[=======================================================================[.rst: +emsdkHack +--------- + +The Emscripten platform doesn't support the use of shared libraries as known by cmake. + +* https://github.com/emscripten-core/emscripten/issues/15276 +* https://github.com/emscripten-core/emscripten/issues/17804 + +This workaround only works due to the way the cmake scripts are loaded. + +Prior to the use of ``project( ... )`` directive we need to set +``CMAKE_PROJECT_INCLUDE=cmake/emscripten.cmake``. +This file will be loaded after the toolchain overriding the settings that +prevent shared library building. + +CMAKE_PROJECT_INCLUDE was Added in version 3.15. +``CMAKE_PROJECT__INCLUDE`` was Added in version 3.17: + +More information on cmake's `code injection`_ + +.. _code injection:https://cmake.org/cmake/help/latest/command/project.html#code-injection + +Overwrite Shared Library Properties to allow shared libs to be generated. +]=======================================================================] +if( EMSCRIPTEN ) + set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE) + set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-sSIDE_MODULE=1") + set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-sSIDE_MODULE=1") + set(CMAKE_SHARED_LIBRARY_SUFFIX) # remove the suffix from the shared lib + set(CMAKE_STRIP FALSE) # used by default in pybind11 on .so modules + + # The Emscripten toolchain sets the default value for EMSCRIPTEN_SYSTEM_PROCESSOR to x86 + # and CMAKE_SYSTEM_PROCESSOR to this value. I don't want that. + set(CMAKE_SYSTEM_PROCESSOR "wasm32" ) + # the above prevents the need for logic like: + #if( ${CMAKE_SYSTEM_NAME} STREQUAL Emscripten ) + # set( SYSTEM_ARCH wasm32 ) + #endif () +endif () diff --git a/cmake/godotcpp.cmake b/cmake/godotcpp.cmake index a5c667796..c6ba53a34 100644 --- a/cmake/godotcpp.cmake +++ b/cmake/godotcpp.cmake @@ -1,13 +1,85 @@ -function( godotcpp_options ) +#[=======================================================================[.rst: +godotcpp.cmake +-------------- + +Because these files are included into the top level CMakelists.txt before the +project directive, it means that + +* ``CMAKE_CURRENT_SOURCE_DIR`` is the location of godot-cpp's CMakeLists.txt +* ``CMAKE_SOURCE_DIR`` is the location where any prior ``project(...)`` + directive was + +]=======================================================================] +include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/common_compiler_flags.cmake) +include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/android.cmake) +include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/ios.cmake) +include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/linux.cmake) +include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos.cmake) +include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/web.cmake) +include( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows.cmake) + +#Silence warning from unused CMAKE_C_COMPILER from toolchain +if( CMAKE_C_COMPILER ) +endif () + +include(ProcessorCount) +ProcessorCount(PROC_MAX) +message( "Auto-detected ${PROC_MAX} CPU cores available for build parallelism." ) + +# List of known platforms +set( PLATFORM_LIST linux macos windows android ios web ) + +# List of known architectures +set( ARCH_LIST universal x86_32 x86_64 arm32 arm64 rv64 ppc32 ppc64 wasm32 ) + +# Function to map processors to known architectures +function( godot_arch_map ALIAS PROC ) + string( TOLOWER "${PROC}" PROC ) + + if( "${PROC}" IN_LIST ARCH_LIST ) + set( ${ALIAS} "${PROC}" PARENT_SCOPE) + return() + endif() + + set( x86_64 "w64;amd64" ) + set( arm32 "armv7" ) + set( arm64 "armv8;arm64v8;aarch64" ) + set( rv64 "rv;riscv;riscv64" ) + set( ppc32 "ppcle;ppc" ) + set( ppc64 "ppc64le" ) + + if( PROC IN_LIST x86_64 ) + set(${ALIAS} "x86_64" PARENT_SCOPE ) + + elseif( PROC IN_LIST arm32 ) + set(${ALIAS} "arm32" PARENT_SCOPE ) + + elseif( PROC IN_LIST arm64 ) + set(${ALIAS} "arm64" PARENT_SCOPE ) + + elseif( PROC IN_LIST rv64 ) + set(${ALIAS} "rv64" PARENT_SCOPE ) + + elseif( PROC IN_LIST ppc32 ) + set(${ALIAS} "ppc32" PARENT_SCOPE ) - #TODO platform - #TODO target + elseif( PROC IN_LIST ppc64 ) + set(${ALIAS} "ppc64" PARENT_SCOPE ) + + else() + set(${ALIAS} "unknown" PARENT_SCOPE ) + endif () +endfunction() + +# Function to define all the options. +function( godotcpp_options ) + #NOTE: platform is managed using toolchain files. # Input from user for GDExtension interface header and the API JSON file set(GODOT_GDEXTENSION_DIR "gdextension" CACHE PATH "Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )" ) set(GODOT_CUSTOM_API_FILE "" CACHE FILEPATH - "Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`) ( /path/to/custom_api_file )") + "Path to a custom GDExtension API JSON file (takes precedence over `GODOT_GDEXTENSION_DIR`) ( /path/to/custom_api_file )") #TODO generate_bindings @@ -19,15 +91,22 @@ function( godotcpp_options ) set(GODOT_PRECISION "single" CACHE STRING "Set the floating-point precision level (single|double)") - #TODO arch + # The arch is typically set by the toolchain + # however for Apple multi-arch setting it here will override. + set( GODOT_ARCH "" CACHE STRING "Target CPU Architecture") + set_property( CACHE GODOT_ARCH PROPERTY STRINGS ${ARCH_LIST} ) + #TODO threads #TODO compiledb #TODO compiledb_file - #TODO build_profile aka cmake preset + + #NOTE: build_profile's equivalent in cmake is CMakePresets.json set(GODOT_USE_HOT_RELOAD "" CACHE BOOL "Enable the extra accounting required to support hot reload. (ON|OFF)") + # Disable exception handling. Godot doesn't use exceptions anywhere, and this + # saves around 20% of binary size and very significant build time (GH-80513). option(GODOT_DISABLE_EXCEPTIONS "Force disabling exception handling code (ON|OFF)" ON ) set( GODOT_SYMBOL_VISIBILITY "hidden" CACHE STRING @@ -36,48 +115,67 @@ function( godotcpp_options ) #TODO optimize #TODO debug_symbols - #TODO dev_build + option( GODOT_DEBUG_SYMBOLS "" OFF ) + option( GODOT_DEV_BUILD "Developer build with dev-only debugging code (DEV_ENABLED)" OFF ) # FIXME These options are not present in SCons, and perhaps should be added there. - option(GODOT_SYSTEM_HEADERS "Expose headers as SYSTEM." ON) - option(GODOT_WARNING_AS_ERROR "Treat warnings as errors" OFF) - - # Run options commands on the following to populate cache for all platforms. - # This type of thing is typically done conditionally - # But as scons shows all options so shall we. - #TODO ios_options() - #TODO linux_options() - #TODO macos_options() - #TODO web_options() - #TODO windows_options() + option( GODOT_SYSTEM_HEADERS "Expose headers as SYSTEM." OFF ) + option( GODOT_WARNING_AS_ERROR "Treat warnings as errors" OFF ) + + # Run options commands on the following to populate cache for all + # platforms. This type of thing is typically done conditionally But as + # scons shows all options so shall we. + android_options() + ios_options() + linux_options() + macos_options() + web_options() + windows_options() endfunction() - +# Function to configure and generate the targets function( godotcpp_generate ) - # Set some helper variables for readability - set( compiler_is_clang "$,$>" ) - set( compiler_is_gnu "$" ) - set( compiler_is_msvc "$" ) - - # CXX_VISIBILITY_PRESET supported values are: default, hidden, protected, and internal - # which is inline with the gcc -fvisibility= - # https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html - # To match the scons options we need to change the text to match the -fvisibility flag - # it is probably worth another PR which changes both to use the flag options + #[[ Multi-Threaded MSVC Compilation + + When using the MSVC compiler the build command -j only specifies + parallel jobs or targets, and not multi-threaded compilation To speed up + compile times on msvc, the /MP flag can be set. But we need to set it + at configure time. + + MSVC is true when the compiler is some version of Microsoft Visual C++ or + another compiler simulating the Visual C++ cl command-line syntax. ]] + if( MSVC ) + math( EXPR PROC_N "(${PROC_MAX}-1) | (${X}-2)>>31 & 1" ) + message( "Using ${PROC_N} cores for multi-threaded compilation.") + # TODO You can override it at configure time with ...." ) + else () + message( "Using ${CMAKE_BUILD_PARALLEL_LEVEL} cores, You can override" + " it at configure time by using -j or --parallel on the build" + " command.") + message( " eg. cmake --build . -j 7 ...") + endif () + + #[[ GODOT_SYMBOL_VISIBLITY + To match the SCons options, the allowed values are "auto", "visible", and "hidden" + This effects the compiler flag -fvisibility=[default|internal|hidden|protected] + The corresponding CMake option CXX_VISIBILITY_PRESET accepts the compiler values. + + TODO: It is probably worth a pull request which changes both to use the compiler values + https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fvisibility + + This performs the necessary conversion + ]] if( ${GODOT_SYMBOL_VISIBILITY} STREQUAL "auto" OR ${GODOT_SYMBOL_VISIBILITY} STREQUAL "visible" ) set( GODOT_SYMBOL_VISIBILITY "default" ) endif () - # Default build type is Debug in the SConstruct - if("${CMAKE_BUILD_TYPE}" STREQUAL "") - set(CMAKE_BUILD_TYPE Debug) - endif() - - # Hot reload is enabled by default in Debug-builds - if( GODOT_USE_HOT_RELOAD STREQUAL "" AND NOT CMAKE_BUILD_TYPE STREQUAL "Release") - set(GODOT_USE_HOT_RELOAD ON) - endif() + # Setup variable to optionally mark headers as SYSTEM + set(GODOT_SYSTEM_HEADERS_ATTRIBUTE "") + if (GODOT_SYSTEM_HEADERS) + set(GODOT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM) + endif () + #[[ Generate Bindings ]] if(NOT DEFINED BITS) set(BITS 32) if(CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -85,67 +183,26 @@ function( godotcpp_generate ) endif(CMAKE_SIZEOF_VOID_P EQUAL 8) endif() - set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json") if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "") # User-defined override. set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}") endif() - if ("${GODOT_PRECISION}" STREQUAL "double") - add_definitions(-DREAL_T_IS_DOUBLE) - endif() - - set( GODOT_COMPILE_FLAGS ) - - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - # using Visual Studio C++ - set(GODOT_COMPILE_FLAGS "/utf-8") # /GF /MP - - if(CMAKE_BUILD_TYPE MATCHES Debug) - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MDd") # /Od /RTC1 /Zi - else() - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MD /O2") # /Oy /GL /Gy - endif(CMAKE_BUILD_TYPE MATCHES Debug) - - add_definitions(-DNOMINMAX) - else() # GCC/Clang - if(CMAKE_BUILD_TYPE MATCHES Debug) - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0 -g") - else() - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3") - endif(CMAKE_BUILD_TYPE MATCHES Debug) - endif() - - # Disable exception handling. Godot doesn't use exceptions anywhere, and this - # saves around 20% of binary size and very significant build time (GH-80513). - if (GODOT_DISABLE_EXCEPTIONS) - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0") - else() - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-exceptions") - endif() - else() - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc") - endif() - endif() - - # Generate source from the bindings file - find_package(Python3 3.4 REQUIRED) # pathlib should be present + # Code Generation option if(GODOT_GENERATE_TEMPLATE_GET_NODE) set(GENERATE_BINDING_PARAMETERS "True") else() set(GENERATE_BINDING_PARAMETERS "False") endif() - execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)" + execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list('${GODOT_GDEXTENSION_API_FILE}', '${CMAKE_CURRENT_BINARY_DIR}', headers=True, sources=True)" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GENERATED_FILES_LIST OUTPUT_STRIP_TRAILING_WHITESPACE ) add_custom_command(OUTPUT ${GENERATED_FILES_LIST} - COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.generate_bindings(\"${GODOT_GDEXTENSION_API_FILE}\", \"${GENERATE_BINDING_PARAMETERS}\", \"${BITS}\", \"${GODOT_PRECISION}\", \"${CMAKE_CURRENT_BINARY_DIR}\")" + COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.generate_bindings('${GODOT_GDEXTENSION_API_FILE}', '${GENERATE_BINDING_PARAMETERS}', '${BITS}', '${GODOT_PRECISION}', '${CMAKE_CURRENT_BINARY_DIR}')" VERBATIM WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE} @@ -153,88 +210,91 @@ function( godotcpp_generate ) COMMENT "Generating bindings" ) - # Get Sources - # As this cmake file was added using 'include(godotcpp)' from the root CMakeLists.txt, - # the ${CMAKE_CURRENT_SOURCE_DIR} is still the root dir. - file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.c**) - file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS include/*.h**) - - # Define our godot-cpp library - add_library(${PROJECT_NAME} STATIC - ${SOURCES} - ${HEADERS} - ${GENERATED_FILES_LIST} - ) - add_library(godot::cpp ALIAS ${PROJECT_NAME}) - - include(${PROJECT_SOURCE_DIR}/cmake/common_compiler_flags.cmake) - - target_compile_features(${PROJECT_NAME} - PRIVATE - cxx_std_17 - ) - - if(GODOT_USE_HOT_RELOAD) - target_compile_definitions(${PROJECT_NAME} PUBLIC HOT_RELOAD_ENABLED) - target_compile_options(${PROJECT_NAME} PUBLIC $<${compiler_is_gnu}:-fno-gnu-unique>) - endif() - - target_compile_definitions(${PROJECT_NAME} PUBLIC - $<$: - DEBUG_ENABLED - DEBUG_METHODS_ENABLED - > - $<${compiler_is_msvc}: - TYPED_METHOD_BIND - > - ) - - target_link_options(${PROJECT_NAME} PRIVATE - $<$: - -static-libgcc - -static-libstdc++ - -Wl,-R,'$$ORIGIN' - > + ### Platform is derived from the toolchain target + # See GeneratorExpressions PLATFORM_ID and CMAKE_SYSTEM_NAME + set( SYSTEM_NAME + $<$:android.${ANDROID_ABI}> + $<$:ios> + $<$:linux> + $<$:macos> + $<$:web> + $<$:windows> + $<$:windows> ) + string(REPLACE ";" "" SYSTEM_NAME "${SYSTEM_NAME}") - # Optionally mark headers as SYSTEM - set(GODOT_SYSTEM_HEADERS_ATTRIBUTE "") - if (GODOT_SYSTEM_HEADERS) - set(GODOT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM) - endif () - - target_include_directories(${PROJECT_NAME} ${GODOT_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC - include - ${CMAKE_CURRENT_BINARY_DIR}/gen/include - ${GODOT_GDEXTENSION_DIR} - ) - - # Add the compile flags - set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS ${GODOT_COMPILE_FLAGS}) - - # Create the correct name (godot.os.build_type.system_bits) - string(TOLOWER "${CMAKE_SYSTEM_NAME}" SYSTEM_NAME) - string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE) - - if(ANDROID) - # Added the android abi after system name - set(SYSTEM_NAME ${SYSTEM_NAME}.${ANDROID_ABI}) - - # Android does not have the bits at the end if you look at the main godot repo build - set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}") + ### Use the arch from the toolchain if it isn't set manually + if( GODOT_ARCH ) + set(SYSTEM_ARCH ${GODOT_ARCH}) else() - set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}.${BITS}") + godot_arch_map( SYSTEM_ARCH ${CMAKE_SYSTEM_PROCESSOR} ) endif() - set_target_properties(${PROJECT_NAME} - PROPERTIES - CXX_EXTENSIONS OFF - POSITION_INDEPENDENT_CODE ON - CXX_VISIBILITY_PRESET ${GODOT_SYMBOL_VISIBILITY} - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" - OUTPUT_NAME "${OUTPUT_NAME}" - ) + ### Define our godot-cpp library targets + foreach ( TARGET_NAME template_debug template_release editor ) + + # Useful genex snippits used in subsequent genex's + set( IS_RELEASE "$") + set( IS_DEV "$") + set( DEBUG_FEATURES "$,$>" ) + set( HOT_RELOAD "$,$>" ) + + # the godot-cpp.* library targets + add_library( ${TARGET_NAME} STATIC ${EXCLUDE} ) + add_library( godot-cpp::${TARGET_NAME} ALIAS ${TARGET_NAME} ) + + file( GLOB_RECURSE GODOTCPP_SOURCES LIST_DIRECTORIES NO CONFIGURE_DEPENDS src/*.cpp ) + + target_sources( ${TARGET_NAME} + PRIVATE + ${GODOTCPP_SOURCES} + ${GENERATED_FILES_LIST} + ) + + target_include_directories( ${TARGET_NAME} ${GODOT_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC + include + ${CMAKE_CURRENT_BINARY_DIR}/gen/include + ${GODOT_GDEXTENSION_DIR} + ) + + set_target_properties( ${TARGET_NAME} + PROPERTIES + CXX_STANDARD 17 + CXX_EXTENSIONS OFF + CXX_VISIBILITY_PRESET ${GODOT_SYMBOL_VISIBILITY} + + COMPILE_WARNING_AS_ERROR ${GODOT_WARNING_AS_ERROR} + POSITION_INDEPENDENT_CODE ON + BUILD_RPATH_USE_ORIGIN ON + + PREFIX lib + OUTPUT_NAME "${PROJECT_NAME}.${SYSTEM_NAME}.${TARGET_NAME}.${SYSTEM_ARCH}" + ARCHIVE_OUTPUT_DIRECTORY "$<1:${CMAKE_BINARY_DIR}/bin>" + + # Things that are handy to know for dependent targets + GODOT_PLATFORM "${SYSTEM_NAME}" + GODOT_TARGET "${TARGET_NAME}" + GODOT_ARCH "${SYSTEM_ARCH}" + ) + + if( CMAKE_SYSTEM_NAME STREQUAL Android ) + android_generate( ${TARGET_NAME} ) + elseif ( CMAKE_SYSTEM_NAME STREQUAL iOS ) + ios_generate( ${TARGET_NAME} ) + elseif ( CMAKE_SYSTEM_NAME STREQUAL Linux ) + linux_generate( ${TARGET_NAME} ) + elseif ( CMAKE_SYSTEM_NAME STREQUAL Darwin ) + macos_generate( ${TARGET_NAME} ) + elseif ( CMAKE_SYSTEM_NAME STREQUAL Emscripten ) + web_generate( ${TARGET_NAME} ) + elseif ( CMAKE_SYSTEM_NAME STREQUAL Windows ) + windows_generate( ${TARGET_NAME} ) + endif () + + endforeach () + + # Added for backwards compatibility with prior cmake solution so that builds dont immediately break + # from a missing target. + add_library( godot::cpp ALIAS template_debug ) endfunction() diff --git a/cmake/ios.cmake b/cmake/ios.cmake new file mode 100644 index 000000000..bb9642210 --- /dev/null +++ b/cmake/ios.cmake @@ -0,0 +1,22 @@ +#[=======================================================================[.rst: +Ios +--- + +This file contains functions for options and configuration for targeting the +Ios platform + +]=======================================================================] +function(ios_options) + # iOS options +endfunction() + +function(ios_generate TARGET_NAME) + + target_compile_definitions(${TARGET_NAME} + PUBLIC + IOS_ENABLED + UNIX_ENABLED + ) + + common_compiler_flags(${TARGET_NAME}) +endfunction() diff --git a/cmake/linux.cmake b/cmake/linux.cmake new file mode 100644 index 000000000..fae620e0e --- /dev/null +++ b/cmake/linux.cmake @@ -0,0 +1,22 @@ +#[=======================================================================[.rst: +Linux +----- + +This file contains functions for options and configuration for targeting the +Linux platform + +]=======================================================================] +function( linux_options ) + # Linux Options +endfunction() + +function( linux_generate TARGET_NAME ) + + target_compile_definitions( ${TARGET_NAME} + PUBLIC + LINUX_ENABLED + UNIX_ENABLED + ) + + common_compiler_flags( ${TARGET_NAME} ) +endfunction() diff --git a/cmake/macos.cmake b/cmake/macos.cmake new file mode 100644 index 000000000..1bb4dbcfb --- /dev/null +++ b/cmake/macos.cmake @@ -0,0 +1,59 @@ +#[=======================================================================[.rst: +MacOS +----- + +This file contains functions for options and configuration for targeting the +MacOS platform + +]=======================================================================] + +# Find Requirements +IF(APPLE) + set( CMAKE_OSX_SYSROOT $ENV{SDKROOT} ) + find_library( COCOA_LIBRARY REQUIRED + NAMES Cocoa + PATHS ${CMAKE_OSX_SYSROOT}/System/Library + PATH_SUFFIXES Frameworks + NO_DEFAULT_PATH) +ENDIF (APPLE) + + +function( macos_options ) + # macos options here +endfunction() + + +function( macos_generate TARGET_NAME ) + + # OSX_ARCHITECTURES does not support generator expressions. + if( NOT GODOT_ARCH OR GODOT_ARCH STREQUAL universal ) + set( OSX_ARCH "x86_64;arm64" ) + set( SYSTEM_ARCH universal ) + else() + set( OSX_ARCH ${GODOT_ARCH} ) + endif() + + set_target_properties( ${TARGET_NAME} + PROPERTIES + + OSX_ARCHITECTURES "${OSX_ARCH}" + ) + + target_compile_definitions(${TARGET_NAME} + PUBLIC + MACOS_ENABLED + UNIX_ENABLED + ) + + target_link_options( ${TARGET_NAME} + PUBLIC + -Wl,-undefined,dynamic_lookup + ) + + target_link_libraries( ${TARGET_NAME} + INTERFACE + ${COCOA_LIBRARY} + ) + + common_compiler_flags( ${TARGET_NAME} ) +endfunction() diff --git a/cmake/web.cmake b/cmake/web.cmake new file mode 100644 index 000000000..b7d6c13aa --- /dev/null +++ b/cmake/web.cmake @@ -0,0 +1,42 @@ +#[=======================================================================[.rst: +Web +--- + +This file contains functions for options and configuration for targeting the +Web platform + +]=======================================================================] + +# Emscripten requires this hack for use of the SHARED option +set( CMAKE_PROJECT_godot-cpp_INCLUDE cmake/emsdkHack.cmake ) + +function( web_options ) + # web options +endfunction() + + +function( web_generate TARGET_NAME ) + + target_compile_definitions(${TARGET_NAME} + PUBLIC + WEB_ENABLED + UNIX_ENABLED + ) + + target_compile_options( ${TARGET_NAME} + PUBLIC + -sSIDE_MODULE + -sSUPPORT_LONGJMP=wasm + -fno-exceptions + ) + + target_link_options( ${TARGET_NAME} + INTERFACE + -sWASM_BIGINT + -sSUPPORT_LONGJMP=wasm + -fvisibility=hidden + -shared + ) + + common_compiler_flags( ${TARGET_NAME} ) +endfunction() diff --git a/cmake/windows.cmake b/cmake/windows.cmake new file mode 100644 index 000000000..bf17f74f9 --- /dev/null +++ b/cmake/windows.cmake @@ -0,0 +1,58 @@ +#[=======================================================================[.rst: +Windows +------- + +This file contains functions for options and configuration for targeting the +Windows platform + +]=======================================================================] + +function( windows_options ) + + option( GODOT_USE_STATIC_CPP "Link MinGW/MSVC C++ runtime libraries statically" ON ) + + option( GODOT_DEBUG_CRT "Compile with MSVC's debug CRT (/MDd)" OFF ) + +endfunction() + +function( windows_generate TARGET_NAME ) + set( IS_MSVC "$" ) + set( IS_CLANG "$,$>" ) + set( NOT_MSVC "$" ) + set( STATIC_CPP "$") + set( DISABLE_EXCEPTIONS "$") + set( DEBUG_CRT "$" ) + + set_target_properties( ${TARGET_NAME} + PROPERTIES + PDB_OUTPUT_DIRECTORY "$<1:${CMAKE_SOURCE_DIR}/bin>" + INTERFACE_MSVC_RUNTIME_LIBRARY + "$>" + ) + + target_compile_definitions( ${TARGET_NAME} + PUBLIC + WINDOWS_ENABLED + $<${IS_MSVC}: + TYPED_METHOD_BIND + NOMINMAX + > + ) + + target_link_options( ${TARGET_NAME} + PUBLIC + + $<${NOT_MSVC}: + -Wl,--no-undefined + $<${STATIC_CPP}: + -static + -static-libgcc + -static-libstdc++ + > + > + + $<${IS_CLANG}:-lstdc++> + ) + + common_compiler_flags( ${TARGET_NAME} ) +endfunction() diff --git a/gdextension/extension_api.json b/gdextension/extension_api.json index 10c2f3446..d674b63d4 100644 --- a/gdextension/extension_api.json +++ b/gdextension/extension_api.json @@ -4,8 +4,8 @@ "version_minor": 3, "version_patch": 0, "version_status": "stable", - "version_build": "official", - "version_full_name": "Godot Engine v4.3.stable.official" + "version_build": "blazium", + "version_full_name": "Blazium Engine v0.1.184.nightly (4.3.stable.blazium)" }, "builtin_class_sizes": [ { @@ -44994,6 +44994,60 @@ "type": "enum::AudioStreamPlayer3D.DopplerTracking" } }, + { + "name": "set_doppler_strength", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 373806689, + "arguments": [ + { + "name": "doppler_strength", + "type": "float", + "meta": "float" + } + ] + }, + { + "name": "get_doppler_strength", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1740695150, + "return_value": { + "type": "float", + "meta": "float" + } + }, + { + "name": "set_doppler_clamp", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 373806689, + "arguments": [ + { + "name": "doppler_clamp", + "type": "float", + "meta": "float" + } + ] + }, + { + "name": "get_doppler_clamp", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1740695150, + "return_value": { + "type": "float", + "meta": "float" + } + }, { "name": "set_stream_paused", "is_const": false, @@ -45252,6 +45306,18 @@ "name": "doppler_tracking", "setter": "set_doppler_tracking", "getter": "get_doppler_tracking" + }, + { + "type": "float", + "name": "doppler_strength", + "setter": "set_doppler_strength", + "getter": "get_doppler_strength" + }, + { + "type": "float", + "name": "doppler_clamp", + "setter": "set_doppler_clamp", + "getter": "get_doppler_clamp" } ] }, @@ -46803,6 +46869,24 @@ "value": 1 } ] + }, + { + "name": "SizeMode", + "is_bitfield": false, + "values": [ + { + "name": "SIZE_MODE_IGNORE", + "value": 0 + }, + { + "name": "SIZE_MODE_FIT_WIDTH", + "value": 1 + }, + { + "name": "SIZE_MODE_FIT_HEIGHT", + "value": 2 + } + ] } ], "methods": [ @@ -46960,7 +47044,7 @@ "hash": 1985162088, "arguments": [ { - "name": "mode", + "name": "action_mode", "type": "enum::BaseButton.ActionMode" } ] @@ -46976,6 +47060,31 @@ "type": "enum::BaseButton.ActionMode" } }, + { + "name": "set_size_mode", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1723990759, + "arguments": [ + { + "name": "size_mode", + "type": "enum::BaseButton.SizeMode" + } + ] + }, + { + "name": "get_size_mode", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2867258028, + "return_value": { + "type": "enum::BaseButton.SizeMode" + } + }, { "name": "set_button_mask", "is_const": false, @@ -47158,6 +47267,12 @@ "setter": "set_action_mode", "getter": "get_action_mode" }, + { + "type": "int", + "name": "size_mode", + "setter": "set_size_mode", + "getter": "get_size_mode" + }, { "type": "int", "name": "button_mask", @@ -50548,6 +50663,13 @@ } ] }, + { + "name": "BlaziumClient", + "is_refcounted": false, + "is_instantiable": false, + "inherits": "Node", + "api_type": "core" + }, { "name": "Bone2D", "is_refcounted": false, @@ -59298,6 +59420,47 @@ "return_value": { "type": "enum::CameraFeed.FeedDataType" } + }, + { + "name": "get_formats", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3995934104, + "return_value": { + "type": "Array" + } + }, + { + "name": "set_format", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 31872775, + "return_value": { + "type": "bool" + }, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + }, + { + "name": "parameters", + "type": "Dictionary" + } + ] + } + ], + "signals": [ + { + "name": "frame_changed" + }, + { + "name": "format_changed" } ], "properties": [ @@ -59312,6 +59475,11 @@ "name": "feed_transform", "setter": "set_transform", "getter": "get_transform" + }, + { + "type": "Array", + "name": "formats", + "getter": "get_formats" } ] }, @@ -69677,6 +69845,104 @@ } ] }, + { + "name": "ColorButton", + "is_refcounted": false, + "is_instantiable": true, + "inherits": "BaseButton", + "api_type": "core", + "methods": [ + { + "name": "set_color_no_signal", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2920490490, + "arguments": [ + { + "name": "color", + "type": "Color" + } + ] + }, + { + "name": "set_color", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2920490490, + "arguments": [ + { + "name": "color", + "type": "Color" + } + ] + }, + { + "name": "get_color", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3444240500, + "return_value": { + "type": "Color" + } + }, + { + "name": "set_flat", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2586408642, + "arguments": [ + { + "name": "enabled", + "type": "bool" + } + ] + }, + { + "name": "is_flat", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + } + ], + "signals": [ + { + "name": "color_changed", + "arguments": [ + { + "name": "color", + "type": "Color" + } + ] + } + ], + "properties": [ + { + "type": "Color", + "name": "color", + "setter": "set_color_no_signal", + "getter": "get_color" + }, + { + "type": "bool", + "name": "flat", + "setter": "set_flat", + "getter": "is_flat" + } + ] + }, { "name": "ColorPicker", "is_refcounted": false, @@ -69759,6 +70025,45 @@ "type": "Color" } }, + { + "name": "set_old_color", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2920490490, + "arguments": [ + { + "name": "color", + "type": "Color" + } + ] + }, + { + "name": "set_display_old_color", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2586408642, + "arguments": [ + { + "name": "display", + "type": "bool" + } + ] + }, + { + "name": "is_displaying_old_color", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, { "name": "set_deferred_mode", "is_const": false, @@ -78233,6 +78538,765 @@ } ] }, + { + "name": "DiscordEmbeddedAppClient", + "is_refcounted": false, + "is_instantiable": true, + "inherits": "ThirdPartyClient", + "api_type": "core", + "enums": [ + { + "name": "DiscordEmbeddedAppOrientationLockState", + "is_bitfield": false, + "values": [ + { + "name": "DISCORD_EMBEDDED_APP_ORIENTATION_LOCK_STATE_UNHANDLED", + "value": -1 + }, + { + "name": "DISCORD_EMBEDDED_APP_ORIENTATION_LOCK_STATE_UNLOCKED", + "value": 1 + }, + { + "name": "DISCORD_EMBEDDED_APP_ORIENTATION_LOCK_STATE_PORTRAIT", + "value": 2 + }, + { + "name": "DISCORD_EMBEDDED_APP_ORIENTATION_LOCK_STATE_LANDSCAPE", + "value": 3 + } + ] + } + ], + "methods": [ + { + "name": "close", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 501894301, + "arguments": [ + { + "name": "code", + "type": "int", + "meta": "int32" + }, + { + "name": "message", + "type": "String" + } + ] + }, + { + "name": "authenticate", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 727016349, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + }, + "arguments": [ + { + "name": "access_token", + "type": "String" + } + ] + }, + { + "name": "authorize", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1798996667, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + }, + "arguments": [ + { + "name": "response_type", + "type": "String" + }, + { + "name": "state", + "type": "String" + }, + { + "name": "prompt", + "type": "String" + }, + { + "name": "scope", + "type": "Array" + } + ] + }, + { + "name": "capture_log", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2708333931, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + }, + "arguments": [ + { + "name": "level", + "type": "String" + }, + { + "name": "message", + "type": "String" + } + ] + }, + { + "name": "encourage_hardware_acceleration", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 772815147, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + } + }, + { + "name": "get_channel", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 727016349, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + }, + "arguments": [ + { + "name": "channel_id", + "type": "String" + } + ] + }, + { + "name": "get_channel_permissions", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 772815147, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + } + }, + { + "name": "get_entitlements", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 772815147, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + } + }, + { + "name": "get_instance_connected_participants", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 772815147, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + } + }, + { + "name": "get_platform_behaviours", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 772815147, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + } + }, + { + "name": "get_skus", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 772815147, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + } + }, + { + "name": "initiate_image_upload", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 772815147, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + } + }, + { + "name": "open_external_link", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 727016349, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + }, + "arguments": [ + { + "name": "url", + "type": "String" + } + ] + }, + { + "name": "open_invite_dialog", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 772815147, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + } + }, + { + "name": "open_share_moment_dialog", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 727016349, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + }, + "arguments": [ + { + "name": "media_url", + "type": "String" + } + ] + }, + { + "name": "set_activity", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3285996244, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + }, + "arguments": [ + { + "name": "activity", + "type": "Dictionary" + } + ] + }, + { + "name": "set_config", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3614744037, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + }, + "arguments": [ + { + "name": "use_interactive_pip", + "type": "bool" + } + ] + }, + { + "name": "set_orientation_lock_state", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2229000133, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + }, + "arguments": [ + { + "name": "lock_state", + "type": "enum::DiscordEmbeddedAppClient.DiscordEmbeddedAppOrientationLockState" + }, + { + "name": "picture_in_picture_lock_state", + "type": "enum::DiscordEmbeddedAppClient.DiscordEmbeddedAppOrientationLockState" + }, + { + "name": "grid_lock_state", + "type": "enum::DiscordEmbeddedAppClient.DiscordEmbeddedAppOrientationLockState" + } + ] + }, + { + "name": "start_purchase", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2708333931, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + }, + "arguments": [ + { + "name": "sku_id", + "type": "String" + }, + { + "name": "pid", + "type": "String" + } + ] + }, + { + "name": "user_settings_get_locale", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 772815147, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + } + }, + { + "name": "subscribe_to_all_events", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3218959716 + }, + { + "name": "is_ready", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 772815147, + "return_value": { + "type": "DiscordEmbeddedAppResponse" + } + }, + { + "name": "is_discord_environment", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2240911060, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_user_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "get_client_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "get_user_instance_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "get_custom_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "get_referrer_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "get_platform", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "get_guild_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "get_channel_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "get_location_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "get_sdk_version", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "get_mobile_app_version", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "get_frame_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + } + ], + "signals": [ + { + "name": "log_updated", + "arguments": [ + { + "name": "command", + "type": "String" + }, + { + "name": "logs", + "type": "String" + } + ] + }, + { + "name": "error", + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + }, + { + "name": "voice_state_update", + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + }, + { + "name": "speaking_start", + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + }, + { + "name": "speaking_stop", + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + }, + { + "name": "activity_layout_mode_update", + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + }, + { + "name": "orientation_update", + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + }, + { + "name": "thermal_state_update", + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + }, + { + "name": "activity_instance_participants_update", + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + }, + { + "name": "entitlement_create", + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + }, + { + "name": "current_guild_member_update", + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + }, + { + "name": "current_user_update", + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + } + ], + "properties": [ + { + "type": "String", + "name": "user_id", + "getter": "get_user_id" + }, + { + "type": "String", + "name": "client_id", + "getter": "get_client_id" + }, + { + "type": "String", + "name": "user_instance_id", + "getter": "get_user_instance_id" + }, + { + "type": "String", + "name": "custom_id", + "getter": "get_custom_id" + }, + { + "type": "String", + "name": "referrer_id", + "getter": "get_referrer_id" + }, + { + "type": "String", + "name": "platform", + "getter": "get_platform" + }, + { + "type": "String", + "name": "guild_id", + "getter": "get_guild_id" + }, + { + "type": "String", + "name": "channel_id", + "getter": "get_channel_id" + }, + { + "type": "String", + "name": "location_id", + "getter": "get_location_id" + }, + { + "type": "String", + "name": "sdk_version", + "getter": "get_sdk_version" + }, + { + "type": "String", + "name": "mobile_app_version", + "getter": "get_mobile_app_version" + }, + { + "type": "String", + "name": "frame_id", + "getter": "get_frame_id" + } + ] + }, + { + "name": "DiscordEmbeddedAppResponse", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "signals": [ + { + "name": "finished", + "arguments": [ + { + "name": "result", + "type": "DiscordEmbeddedAppResult" + } + ] + } + ] + }, + { + "name": "DiscordEmbeddedAppResult", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "methods": [ + { + "name": "get_data", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3102165223, + "return_value": { + "type": "Dictionary" + } + }, + { + "name": "has_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + } + ], + "properties": [ + { + "type": "Dictionary", + "name": "data", + "getter": "get_data" + }, + { + "type": "String", + "name": "error", + "getter": "get_error" + } + ] + }, { "name": "DisplayServer", "is_refcounted": false, @@ -86956,6 +88020,17 @@ "type": "PackedStringArray" } }, + { + "name": "get_open_scenes_roots", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3995934104, + "return_value": { + "type": "Array" + } + }, { "name": "get_edited_scene_root", "is_const": true, @@ -99725,6 +100800,927 @@ } ] }, + { + "name": "FoldableContainer", + "is_refcounted": false, + "is_instantiable": true, + "inherits": "Container", + "api_type": "core", + "enums": [ + { + "name": "TitlePosition", + "is_bitfield": false, + "values": [ + { + "name": "POSITION_TOP", + "value": 0 + }, + { + "name": "POSITION_BOTTOM", + "value": 1 + } + ] + } + ], + "methods": [ + { + "name": "fold", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3218959716 + }, + { + "name": "expand", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3218959716 + }, + { + "name": "set_folded", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2586408642, + "arguments": [ + { + "name": "folded", + "type": "bool" + } + ] + }, + { + "name": "is_folded", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "set_expanded", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2586408642, + "arguments": [ + { + "name": "expanded", + "type": "bool" + } + ] + }, + { + "name": "is_expanded", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "set_foldable_group", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3001390597, + "arguments": [ + { + "name": "button_group", + "type": "FoldableGroup" + } + ] + }, + { + "name": "get_foldable_group", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 66499518, + "return_value": { + "type": "FoldableGroup" + } + }, + { + "name": "set_text", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "text", + "type": "String" + } + ] + }, + { + "name": "get_text", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "set_title_alignment", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2312603777, + "arguments": [ + { + "name": "alignment", + "type": "enum::HorizontalAlignment" + } + ] + }, + { + "name": "get_title_alignment", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 341400642, + "return_value": { + "type": "enum::HorizontalAlignment" + } + }, + { + "name": "set_language", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "language", + "type": "String" + } + ] + }, + { + "name": "get_language", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "set_text_direction", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 119160795, + "arguments": [ + { + "name": "text_direction", + "type": "enum::Control.TextDirection" + } + ] + }, + { + "name": "get_text_direction", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 797257663, + "return_value": { + "type": "enum::Control.TextDirection" + } + }, + { + "name": "set_text_overrun_behavior", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1008890932, + "arguments": [ + { + "name": "overrun_behavior", + "type": "enum::TextServer.OverrunBehavior" + } + ] + }, + { + "name": "get_text_overrun_behavior", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3779142101, + "return_value": { + "type": "enum::TextServer.OverrunBehavior" + } + }, + { + "name": "set_title_position", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2276829442, + "arguments": [ + { + "name": "title_position", + "type": "enum::FoldableContainer.TitlePosition" + } + ] + }, + { + "name": "get_title_position", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3028840207, + "return_value": { + "type": "enum::FoldableContainer.TitlePosition" + } + }, + { + "name": "add_button", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2182786679, + "arguments": [ + { + "name": "icon", + "type": "Texture2D", + "default_value": "null" + }, + { + "name": "position", + "type": "int", + "meta": "int32", + "default_value": "-1" + }, + { + "name": "id", + "type": "int", + "meta": "int32", + "default_value": "-1" + } + ] + }, + { + "name": "remove_button", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1286410249, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "set_button_count", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1286410249, + "arguments": [ + { + "name": "count", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "get_button_count", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3905245786, + "return_value": { + "type": "int", + "meta": "int32" + } + }, + { + "name": "get_button_rect", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3327874267, + "return_value": { + "type": "Rect2" + }, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "clear", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3218959716 + }, + { + "name": "set_button_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3937882851, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + }, + { + "name": "id", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "get_button_id", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 923996154, + "return_value": { + "type": "int", + "meta": "int32" + }, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "move_button", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 50157827, + "return_value": { + "type": "int", + "meta": "int32" + }, + "arguments": [ + { + "name": "from", + "type": "int", + "meta": "int32" + }, + { + "name": "to", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "get_button_index", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 923996154, + "return_value": { + "type": "int", + "meta": "int32" + }, + "arguments": [ + { + "name": "id", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "set_button_toggle_mode", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 300928843, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + }, + { + "name": "enabled", + "type": "bool" + } + ] + }, + { + "name": "get_button_toggle_mode", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1116898809, + "return_value": { + "type": "bool" + }, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "set_button_toggled", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 300928843, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + }, + { + "name": "toggled_on", + "type": "bool" + } + ] + }, + { + "name": "is_button_toggled", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1116898809, + "return_value": { + "type": "bool" + }, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "set_button_icon", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 666127730, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + }, + { + "name": "icon", + "type": "Texture2D" + } + ] + }, + { + "name": "get_button_icon", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3536238170, + "return_value": { + "type": "Texture2D" + }, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "set_button_tooltip", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 501894301, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + }, + { + "name": "tooltip", + "type": "String" + } + ] + }, + { + "name": "get_button_tooltip", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 844755477, + "return_value": { + "type": "String" + }, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "set_button_disabled", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 300928843, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + }, + { + "name": "disabled", + "type": "bool" + } + ] + }, + { + "name": "is_button_disabled", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1116898809, + "return_value": { + "type": "bool" + }, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "set_button_visible", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 300928843, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + }, + { + "name": "hidden", + "type": "bool" + } + ] + }, + { + "name": "is_button_visible", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1116898809, + "return_value": { + "type": "bool" + }, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "set_button_auto_hide", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 300928843, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + }, + { + "name": "auto_hide", + "type": "bool" + } + ] + }, + { + "name": "is_button_auto_hide", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1116898809, + "return_value": { + "type": "bool" + }, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "set_button_metadata", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2152698145, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + }, + { + "name": "metadata", + "type": "Variant" + } + ] + }, + { + "name": "get_button_metadata", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 4227898402, + "return_value": { + "type": "Variant" + }, + "arguments": [ + { + "name": "index", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "get_button_at_position", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3820158470, + "return_value": { + "type": "int", + "meta": "int32" + }, + "arguments": [ + { + "name": "position", + "type": "Vector2" + } + ] + } + ], + "signals": [ + { + "name": "folding_changed", + "arguments": [ + { + "name": "is_folded", + "type": "bool" + } + ] + }, + { + "name": "button_pressed", + "arguments": [ + { + "name": "index", + "type": "int" + } + ] + }, + { + "name": "button_toggled", + "arguments": [ + { + "name": "toggled_on", + "type": "bool" + }, + { + "name": "index", + "type": "int" + } + ] + } + ], + "properties": [ + { + "type": "bool", + "name": "folded", + "setter": "set_folded", + "getter": "is_folded" + }, + { + "type": "String", + "name": "text", + "setter": "set_text", + "getter": "get_text" + }, + { + "type": "int", + "name": "title_alignment", + "setter": "set_title_alignment", + "getter": "get_title_alignment" + }, + { + "type": "int", + "name": "title_position", + "setter": "set_title_position", + "getter": "get_title_position" + }, + { + "type": "int", + "name": "text_overrun_behavior", + "setter": "set_text_overrun_behavior", + "getter": "get_text_overrun_behavior" + }, + { + "type": "FoldableGroup", + "name": "foldable_group", + "setter": "set_foldable_group", + "getter": "get_foldable_group" + }, + { + "type": "int", + "name": "button_count", + "setter": "set_button_count", + "getter": "get_button_count" + }, + { + "type": "int", + "name": "text_direction", + "setter": "set_text_direction", + "getter": "get_text_direction" + }, + { + "type": "String", + "name": "language", + "setter": "set_language", + "getter": "get_language" + } + ] + }, + { + "name": "FoldableGroup", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "Resource", + "api_type": "core", + "methods": [ + { + "name": "get_expanded_container", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3414248291, + "return_value": { + "type": "FoldableContainer" + } + }, + { + "name": "get_containers", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2915620761, + "return_value": { + "type": "typedarray::FoldableContainer" + } + }, + { + "name": "set_allow_folding_all", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2586408642, + "arguments": [ + { + "name": "enabled", + "type": "bool" + } + ] + }, + { + "name": "is_allow_folding_all", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2240911060, + "return_value": { + "type": "bool" + } + } + ], + "signals": [ + { + "name": "expanded", + "arguments": [ + { + "name": "container", + "type": "FoldableContainer" + } + ] + } + ], + "properties": [ + { + "type": "bool", + "name": "allow_folding_all", + "setter": "set_allow_folding_all", + "getter": "is_allow_folding_all" + } + ] + }, { "name": "Font", "is_refcounted": true, @@ -101108,6 +103104,31 @@ "type": "enum::TextServer.SubpixelPositioning" } }, + { + "name": "set_lcd_subpixel_layout", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1893246148, + "arguments": [ + { + "name": "subpixel_layout", + "type": "enum::TextServer.FontLCDSubpixelLayout" + } + ] + }, + { + "name": "get_lcd_subpixel_layout", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1912389403, + "return_value": { + "type": "enum::TextServer.FontLCDSubpixelLayout" + } + }, { "name": "set_oversampling", "is_const": false, @@ -102655,6 +104676,12 @@ "setter": "set_subpixel_positioning", "getter": "get_subpixel_positioning" }, + { + "type": "int", + "name": "lcd_subpixel_layout", + "setter": "set_lcd_subpixel_layout", + "getter": "get_lcd_subpixel_layout" + }, { "type": "bool", "name": "multichannel_signed_distance_field", @@ -111430,6 +113457,271 @@ } ] }, + { + "name": "GameServerInfo", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "Resource", + "api_type": "core", + "methods": [ + { + "name": "get_id", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_game_name", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_ip_address", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_port", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3905245786, + "return_value": { + "type": "int", + "meta": "int32" + } + }, + { + "name": "get_description", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_max_players", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3905245786, + "return_value": { + "type": "int", + "meta": "int32" + } + }, + { + "name": "get_players", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3905245786, + "return_value": { + "type": "int", + "meta": "int32" + } + }, + { + "name": "get_version", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "set_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "id", + "type": "String" + } + ] + }, + { + "name": "set_game_name", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "game_name", + "type": "String" + } + ] + }, + { + "name": "set_ip_address", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "ip_address", + "type": "String" + } + ] + }, + { + "name": "set_port", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1286410249, + "arguments": [ + { + "name": "port", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "set_description", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "description", + "type": "String" + } + ] + }, + { + "name": "set_max_players", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1286410249, + "arguments": [ + { + "name": "max_players", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "set_players", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1286410249, + "arguments": [ + { + "name": "players", + "type": "int", + "meta": "int32" + } + ] + }, + { + "name": "set_version", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "version", + "type": "String" + } + ] + } + ], + "properties": [ + { + "type": "String", + "name": "id", + "setter": "set_id", + "getter": "get_id" + }, + { + "type": "String", + "name": "game_name", + "setter": "set_game_name", + "getter": "get_game_name" + }, + { + "type": "String", + "name": "ip_address", + "setter": "set_ip_address", + "getter": "get_ip_address" + }, + { + "type": "String", + "name": "port", + "setter": "set_port", + "getter": "get_port" + }, + { + "type": "String", + "name": "description", + "setter": "set_description", + "getter": "get_description" + }, + { + "type": "int", + "name": "max_players", + "setter": "set_max_players", + "getter": "get_max_players" + }, + { + "type": "int", + "name": "players", + "setter": "set_players", + "getter": "get_players" + }, + { + "type": "String", + "name": "version", + "setter": "set_version", + "getter": "get_version" + } + ] + }, { "name": "Generic6DOFJoint3D", "is_refcounted": false, @@ -127822,6 +130114,49 @@ } ] }, + { + "name": "JWT", + "is_refcounted": false, + "is_instantiable": true, + "inherits": "Object", + "api_type": "core", + "methods": [ + { + "name": "get_header", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2786125124, + "return_value": { + "type": "Dictionary" + }, + "arguments": [ + { + "name": "jwt", + "type": "String" + } + ] + }, + { + "name": "get_payload", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2786125124, + "return_value": { + "type": "Dictionary" + }, + "arguments": [ + { + "name": "jwt", + "type": "String" + } + ] + } + ] + }, { "name": "JavaClass", "is_refcounted": true, @@ -128011,6 +130346,22 @@ "is_instantiable": false, "inherits": "Node2D", "api_type": "core", + "enums": [ + { + "name": "DisableMode", + "is_bitfield": false, + "values": [ + { + "name": "DISABLE_MODE_REMOVE", + "value": 0 + }, + { + "name": "DISABLE_MODE_KEEP_ACTIVE", + "value": 1 + } + ] + } + ], "methods": [ { "name": "set_node_a", @@ -128089,6 +130440,31 @@ "meta": "float" } }, + { + "name": "set_disable_mode", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3394248226, + "arguments": [ + { + "name": "mode", + "type": "enum::Joint2D.DisableMode" + } + ] + }, + { + "name": "get_disable_mode", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2910099652, + "return_value": { + "type": "enum::Joint2D.DisableMode" + } + }, { "name": "set_exclude_nodes_from_collision", "is_const": false, @@ -128150,6 +130526,12 @@ "name": "disable_collision", "setter": "set_exclude_nodes_from_collision", "getter": "get_exclude_nodes_from_collision" + }, + { + "type": "int", + "name": "disable_mode", + "setter": "set_disable_mode", + "getter": "get_disable_mode" } ] }, @@ -128159,6 +130541,22 @@ "is_instantiable": false, "inherits": "Node3D", "api_type": "core", + "enums": [ + { + "name": "DisableMode", + "is_bitfield": false, + "values": [ + { + "name": "DISABLE_MODE_REMOVE", + "value": 0 + }, + { + "name": "DISABLE_MODE_KEEP_ACTIVE", + "value": 1 + } + ] + } + ], "methods": [ { "name": "set_node_a", @@ -128262,6 +130660,31 @@ "type": "bool" } }, + { + "name": "set_disable_mode", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 515496447, + "arguments": [ + { + "name": "mode", + "type": "enum::Joint3D.DisableMode" + } + ] + }, + { + "name": "get_disable_mode", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2768499949, + "return_value": { + "type": "enum::Joint3D.DisableMode" + } + }, { "name": "get_rid", "is_const": true, @@ -128298,6 +130721,12 @@ "name": "exclude_nodes_from_collision", "setter": "set_exclude_nodes_from_collision", "getter": "get_exclude_nodes_from_collision" + }, + { + "type": "int", + "name": "disable_mode", + "setter": "set_disable_mode", + "getter": "get_disable_mode" } ] }, @@ -133821,6 +136250,33 @@ } ], "methods": [ + { + "name": "has_ime_text", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "cancel_ime", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3218959716 + }, + { + "name": "apply_ime", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3218959716 + }, { "name": "set_horizontal_alignment", "is_const": false, @@ -133846,6 +136302,58 @@ "type": "enum::HorizontalAlignment" } }, + { + "name": "edit", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3218959716 + }, + { + "name": "unedit", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3218959716 + }, + { + "name": "is_editing", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "set_keep_editing_on_text_submit", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2586408642, + "arguments": [ + { + "name": "enable", + "type": "bool" + } + ] + }, + { + "name": "is_editing_kept_on_text_submit", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, { "name": "clear", "is_const": false, @@ -134788,6 +137296,15 @@ "type": "String" } ] + }, + { + "name": "editing_toggled", + "arguments": [ + { + "name": "toggled_on", + "type": "bool" + } + ] } ], "properties": [ @@ -134821,6 +137338,12 @@ "setter": "set_editable", "getter": "is_editable" }, + { + "type": "bool", + "name": "keep_editing_on_text_submit", + "setter": "set_keep_editing_on_text_submit", + "getter": "is_editing_kept_on_text_submit" + }, { "type": "bool", "name": "expand_to_text_length", @@ -135221,6 +137744,1483 @@ } ] }, + { + "name": "LobbyClient", + "is_refcounted": false, + "is_instantiable": true, + "inherits": "BlaziumClient", + "api_type": "core", + "methods": [ + { + "name": "set_server_url", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "server_url", + "type": "String" + } + ] + }, + { + "name": "get_server_url", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "set_reconnection_token", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "reconnection_token", + "type": "String" + } + ] + }, + { + "name": "get_reconnection_token", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "set_game_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "game_id", + "type": "String" + } + ] + }, + { + "name": "get_game_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "is_host", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2240911060, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_connected", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2240911060, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_lobby", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2759059446, + "return_value": { + "type": "LobbyInfo" + } + }, + { + "name": "get_peer", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 899568590, + "return_value": { + "type": "LobbyPeer" + } + }, + { + "name": "get_peers", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2915620761, + "return_value": { + "type": "typedarray::LobbyPeer" + } + }, + { + "name": "get_host_data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2382534195, + "return_value": { + "type": "Dictionary" + } + }, + { + "name": "get_peer_data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2382534195, + "return_value": { + "type": "Dictionary" + } + }, + { + "name": "set_override_discord_path", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "override_discord_path", + "type": "String" + } + ] + }, + { + "name": "get_override_discord_path", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "connect_to_lobby", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 402759040, + "return_value": { + "type": "LobbyResponse" + } + }, + { + "name": "disconnect_from_lobby", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 402759040, + "return_value": { + "type": "LobbyResponse" + } + }, + { + "name": "create_lobby", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1782804803, + "return_value": { + "type": "ViewLobbyResponse" + }, + "arguments": [ + { + "name": "title", + "type": "String" + }, + { + "name": "sealed", + "type": "bool" + }, + { + "name": "tags", + "type": "Dictionary", + "default_value": "{}" + }, + { + "name": "max_players", + "type": "int", + "meta": "int32", + "default_value": "4" + }, + { + "name": "password", + "type": "String", + "default_value": "\"\"" + } + ] + }, + { + "name": "join_lobby", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3724509716, + "return_value": { + "type": "ViewLobbyResponse" + }, + "arguments": [ + { + "name": "lobby_id", + "type": "String" + }, + { + "name": "password", + "type": "String", + "default_value": "\"\"" + } + ] + }, + { + "name": "leave_lobby", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 402759040, + "return_value": { + "type": "LobbyResponse" + } + }, + { + "name": "list_lobbies", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 402759040, + "return_value": { + "type": "LobbyResponse" + } + }, + { + "name": "kick_peer", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3186253920, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "peer_id", + "type": "String" + } + ] + }, + { + "name": "send_chat_message", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3186253920, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "chat_message", + "type": "String" + } + ] + }, + { + "name": "set_lobby_ready", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 668034168, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "ready", + "type": "bool" + } + ] + }, + { + "name": "add_lobby_tags", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3614381552, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "tags", + "type": "Dictionary" + } + ] + }, + { + "name": "del_lobby_tags", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2785274044, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "keys", + "type": "typedarray::String" + } + ] + }, + { + "name": "set_lobby_sealed", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 668034168, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "seal", + "type": "bool" + } + ] + }, + { + "name": "notify_lobby", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1532202378, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "data", + "type": "Variant" + } + ] + }, + { + "name": "notify_peer", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1920983225, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "data", + "type": "Variant" + }, + { + "name": "target_peer", + "type": "String" + } + ] + }, + { + "name": "add_peer_user_data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3614381552, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + }, + { + "name": "del_peer_user_data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2785274044, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "keys", + "type": "typedarray::String" + } + ] + }, + { + "name": "add_lobby_data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2853357623, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "data", + "type": "Dictionary" + }, + { + "name": "is_private", + "type": "bool", + "default_value": "false" + } + ] + }, + { + "name": "del_lobby_data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3369593485, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "keys", + "type": "typedarray::String" + }, + { + "name": "is_private", + "type": "bool", + "default_value": "false" + } + ] + }, + { + "name": "add_peer_data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2278039757, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "data", + "type": "Dictionary" + }, + { + "name": "target_peer", + "type": "String" + }, + { + "name": "is_private", + "type": "bool", + "default_value": "false" + } + ] + }, + { + "name": "del_peer_data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2848941423, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "keys", + "type": "typedarray::String" + }, + { + "name": "target_peer", + "type": "String" + }, + { + "name": "is_private", + "type": "bool", + "default_value": "false" + } + ] + }, + { + "name": "add_peers_data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2853357623, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "data", + "type": "Dictionary" + }, + { + "name": "is_private", + "type": "bool", + "default_value": "false" + } + ] + }, + { + "name": "del_peers_data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3369593485, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "keys", + "type": "typedarray::String" + }, + { + "name": "is_private", + "type": "bool", + "default_value": "false" + } + ] + } + ], + "signals": [ + { + "name": "connected_to_lobby", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + }, + { + "name": "reconnection_token", + "type": "String" + } + ] + }, + { + "name": "disconnected_from_lobby", + "arguments": [ + { + "name": "reason", + "type": "String" + } + ] + }, + { + "name": "received_peer_user_data", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + }, + { + "name": "data", + "type": "Object" + } + ] + }, + { + "name": "lobby_notified", + "arguments": [ + { + "name": "data", + "type": "Object" + }, + { + "name": "from_peer", + "type": "LobbyPeer" + } + ] + }, + { + "name": "received_peer_data", + "arguments": [ + { + "name": "data", + "type": "Object" + }, + { + "name": "to_peer", + "type": "LobbyPeer" + }, + { + "name": "is_private", + "type": "bool" + } + ] + }, + { + "name": "received_lobby_data", + "arguments": [ + { + "name": "data", + "type": "Object" + }, + { + "name": "is_private", + "type": "bool" + } + ] + }, + { + "name": "lobby_created", + "arguments": [ + { + "name": "lobby", + "type": "LobbyInfo" + }, + { + "name": "peers", + "type": "typedarray::LobbyPeer" + } + ] + }, + { + "name": "lobby_joined", + "arguments": [ + { + "name": "lobby", + "type": "LobbyInfo" + }, + { + "name": "peers", + "type": "typedarray::LobbyPeer" + } + ] + }, + { + "name": "lobby_left", + "arguments": [ + { + "name": "kicked", + "type": "bool" + } + ] + }, + { + "name": "lobby_sealed", + "arguments": [ + { + "name": "sealed", + "type": "bool" + } + ] + }, + { + "name": "lobby_tagged", + "arguments": [ + { + "name": "tags", + "type": "Dictionary" + } + ] + }, + { + "name": "lobbies_listed", + "arguments": [ + { + "name": "lobbies", + "type": "typedarray::LobbyInfo" + } + ] + }, + { + "name": "peer_joined", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + } + ] + }, + { + "name": "peer_reconnected", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + } + ] + }, + { + "name": "peer_left", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + }, + { + "name": "kicked", + "type": "bool" + } + ] + }, + { + "name": "peer_disconnected", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + } + ] + }, + { + "name": "peer_messaged", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + }, + { + "name": "chat_message", + "type": "String" + } + ] + }, + { + "name": "peer_ready", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + }, + { + "name": "is_ready", + "type": "bool" + } + ] + }, + { + "name": "log_updated", + "arguments": [ + { + "name": "command", + "type": "String" + }, + { + "name": "logs", + "type": "String" + } + ] + } + ], + "properties": [ + { + "type": "String", + "name": "server_url", + "setter": "set_server_url", + "getter": "get_server_url" + }, + { + "type": "String", + "name": "reconnection_token", + "setter": "set_reconnection_token", + "getter": "get_reconnection_token" + }, + { + "type": "String", + "name": "game_id", + "setter": "set_game_id", + "getter": "get_game_id" + }, + { + "type": "bool", + "name": "connected", + "getter": "get_connected" + }, + { + "type": "LobbyInfo", + "name": "lobby", + "getter": "get_lobby" + }, + { + "type": "LobbyPeer", + "name": "peer", + "getter": "get_peer" + }, + { + "type": "typedarray::LobbyPeer", + "name": "peers", + "getter": "get_peers" + }, + { + "type": "Dictionary", + "name": "host_data", + "getter": "get_host_data" + }, + { + "type": "Dictionary", + "name": "peer_data", + "getter": "get_peer_data" + } + ] + }, + { + "name": "LobbyInfo", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "Resource", + "api_type": "core", + "methods": [ + { + "name": "get_host", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_max_players", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3905245786, + "return_value": { + "type": "int", + "meta": "int32" + } + }, + { + "name": "is_sealed", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "is_password_protected", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_id", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_lobby_name", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_players", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3905245786, + "return_value": { + "type": "int", + "meta": "int32" + } + }, + { + "name": "get_tags", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3102165223, + "return_value": { + "type": "Dictionary" + } + }, + { + "name": "get_data", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3102165223, + "return_value": { + "type": "Dictionary" + } + } + ], + "properties": [ + { + "type": "String", + "name": "id", + "getter": "get_id" + }, + { + "type": "String", + "name": "tags", + "getter": "get_tags" + }, + { + "type": "Dictionary", + "name": "data", + "getter": "get_data" + }, + { + "type": "String", + "name": "lobby_name", + "getter": "get_lobby_name" + }, + { + "type": "int", + "name": "players", + "getter": "get_players" + }, + { + "type": "String", + "name": "host", + "getter": "get_host" + }, + { + "type": "int", + "name": "max_players", + "getter": "get_max_players" + }, + { + "type": "bool", + "name": "sealed", + "getter": "is_sealed" + }, + { + "type": "bool", + "name": "password_protected", + "getter": "is_password_protected" + } + ] + }, + { + "name": "LobbyPeer", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "Resource", + "api_type": "core", + "methods": [ + { + "name": "get_id", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_user_data", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3102165223, + "return_value": { + "type": "Dictionary" + } + }, + { + "name": "is_ready", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "is_disconnected", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_data", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3102165223, + "return_value": { + "type": "Dictionary" + } + }, + { + "name": "get_order_id", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3905245786, + "return_value": { + "type": "int", + "meta": "int32" + } + } + ], + "properties": [ + { + "type": "String", + "name": "id", + "getter": "get_id" + }, + { + "type": "Dictionary", + "name": "user_data", + "getter": "get_user_data" + }, + { + "type": "bool", + "name": "disconnected", + "getter": "is_disconnected" + }, + { + "type": "bool", + "name": "ready", + "getter": "is_ready" + }, + { + "type": "Dictionary", + "name": "data", + "getter": "get_data" + }, + { + "type": "int", + "name": "order_id", + "getter": "get_order_id" + } + ] + }, + { + "name": "LobbyResponse", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "signals": [ + { + "name": "finished", + "arguments": [ + { + "name": "result", + "type": "LobbyResult" + } + ] + } + ] + }, + { + "name": "LobbyResult", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "methods": [ + { + "name": "has_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + } + ], + "properties": [ + { + "type": "String", + "name": "error", + "getter": "get_error" + } + ] + }, + { + "name": "LoginClient", + "is_refcounted": false, + "is_instantiable": true, + "inherits": "BlaziumClient", + "api_type": "core", + "methods": [ + { + "name": "request_login_info", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1090734509, + "return_value": { + "type": "LoginResponse" + }, + "arguments": [ + { + "name": "login_type", + "type": "String" + } + ] + }, + { + "name": "set_server_url", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "server_url", + "type": "String" + } + ] + }, + { + "name": "get_server_url", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "set_game_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "game_id", + "type": "String" + } + ] + }, + { + "name": "get_game_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "get_connected", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2240911060, + "return_value": { + "type": "bool" + } + }, + { + "name": "set_override_discord_path", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "override_discord_path", + "type": "String" + } + ] + }, + { + "name": "get_override_discord_path", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "connect_to_server", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1056366657, + "return_value": { + "type": "LoginResponse" + } + }, + { + "name": "disconnect_from_server", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3218959716 + } + ], + "signals": [ + { + "name": "log_updated", + "arguments": [ + { + "name": "command", + "type": "String" + }, + { + "name": "logs", + "type": "String" + } + ] + }, + { + "name": "disconnected_from_server", + "arguments": [ + { + "name": "reason", + "type": "String" + } + ] + }, + { + "name": "connected_to_server" + }, + { + "name": "received_jwt", + "arguments": [ + { + "name": "jwt", + "type": "String" + }, + { + "name": "type", + "type": "String" + }, + { + "name": "access_token", + "type": "String" + } + ] + } + ], + "properties": [ + { + "type": "String", + "name": "server_url", + "setter": "set_server_url", + "getter": "get_server_url" + }, + { + "type": "String", + "name": "game_id", + "setter": "set_game_id", + "getter": "get_game_id" + }, + { + "type": "bool", + "name": "connected", + "getter": "get_connected" + } + ] + }, + { + "name": "LoginResponse", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "signals": [ + { + "name": "finished", + "arguments": [ + { + "name": "result", + "type": "LoginResult" + } + ] + } + ] + }, + { + "name": "LoginResult", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "methods": [ + { + "name": "get_login_url", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_login_type", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "has_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + } + ], + "properties": [ + { + "type": "String", + "name": "error", + "getter": "get_error" + }, + { + "type": "String", + "name": "login_url", + "getter": "get_login_url" + }, + { + "type": "String", + "name": "login_type", + "getter": "get_login_type" + } + ] + }, { "name": "MainLoop", "is_refcounted": false, @@ -135551,6 +139551,293 @@ } ] }, + { + "name": "MasterServerClient", + "is_refcounted": false, + "is_instantiable": true, + "inherits": "BlaziumClient", + "api_type": "core", + "methods": [ + { + "name": "create_game", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 976731373, + "return_value": { + "type": "MasterServerResponse" + }, + "arguments": [ + { + "name": "game_server_info", + "type": "GameServerInfo" + } + ] + }, + { + "name": "update_game", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 976731373, + "return_value": { + "type": "MasterServerResponse" + }, + "arguments": [ + { + "name": "game_server_info", + "type": "GameServerInfo" + } + ] + }, + { + "name": "recent_games", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1841224375, + "return_value": { + "type": "MasterServerListResponse" + } + }, + { + "name": "set_server_url", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "server_url", + "type": "String" + } + ] + }, + { + "name": "get_server_url", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "set_game_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "game_id", + "type": "String" + } + ] + }, + { + "name": "get_game_id", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "set_override_discord_path", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "override_discord_path", + "type": "String" + } + ] + }, + { + "name": "get_override_discord_path", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + } + ], + "properties": [ + { + "type": "String", + "name": "server_url", + "setter": "set_server_url", + "getter": "get_server_url" + }, + { + "type": "String", + "name": "game_id", + "setter": "set_game_id", + "getter": "get_game_id" + } + ] + }, + { + "name": "MasterServerListResponse", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "signals": [ + { + "name": "finished", + "arguments": [ + { + "name": "result", + "type": "MasterServerListResult" + } + ] + } + ] + }, + { + "name": "MasterServerListResult", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "methods": [ + { + "name": "has_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_results", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3995934104, + "return_value": { + "type": "typedarray::GameServerInfo" + } + } + ], + "properties": [ + { + "type": "String", + "name": "error", + "getter": "get_error" + }, + { + "type": "GameServerInfo", + "name": "results", + "getter": "get_results" + } + ] + }, + { + "name": "MasterServerResponse", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "signals": [ + { + "name": "finished", + "arguments": [ + { + "name": "result", + "type": "MasterServerResult" + } + ] + } + ] + }, + { + "name": "MasterServerResult", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "methods": [ + { + "name": "has_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_result", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 358505447, + "return_value": { + "type": "GameServerInfo" + } + } + ], + "properties": [ + { + "type": "String", + "name": "error", + "getter": "get_error" + }, + { + "type": "GameServerInfo", + "name": "result", + "getter": "get_result" + } + ] + }, { "name": "Material", "is_refcounted": true, @@ -145865,6 +150152,31 @@ "type": "bool" } }, + { + "name": "set_navigation_map", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2722037293, + "arguments": [ + { + "name": "navigation_map", + "type": "RID" + } + ] + }, + { + "name": "get_navigation_map", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2944877500, + "return_value": { + "type": "RID" + } + }, { "name": "set_bidirectional", "is_const": false, @@ -146197,6 +150509,31 @@ "type": "bool" } }, + { + "name": "set_navigation_map", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2722037293, + "arguments": [ + { + "name": "navigation_map", + "type": "RID" + } + ] + }, + { + "name": "get_navigation_map", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2944877500, + "return_value": { + "type": "RID" + } + }, { "name": "set_bidirectional", "is_const": false, @@ -147780,6 +152117,17 @@ "return_value": { "type": "Array" } + }, + { + "name": "get_bounds", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3248174, + "return_value": { + "type": "Rect2" + } } ], "properties": [ @@ -148025,6 +152373,17 @@ "return_value": { "type": "Array" } + }, + { + "name": "get_bounds", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1021181044, + "return_value": { + "type": "AABB" + } } ], "properties": [ @@ -167208,7 +171567,7 @@ }, "arguments": [ { - "name": "pck_name", + "name": "pck_path", "type": "String" }, { @@ -167275,6 +171634,294 @@ } ] }, + { + "name": "POGRClient", + "is_refcounted": false, + "is_instantiable": true, + "inherits": "BlaziumClient", + "api_type": "core", + "methods": [ + { + "name": "init", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2607034771, + "return_value": { + "type": "POGRResponse" + } + }, + { + "name": "end", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2607034771, + "return_value": { + "type": "POGRResponse" + } + }, + { + "name": "data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3646189709, + "return_value": { + "type": "POGRResponse" + }, + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + }, + { + "name": "event", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3593940661, + "return_value": { + "type": "POGRResponse" + }, + "arguments": [ + { + "name": "event_name", + "type": "String" + }, + { + "name": "event_data", + "type": "Dictionary" + }, + { + "name": "event_flag", + "type": "String" + }, + { + "name": "event_key", + "type": "String" + }, + { + "name": "event_type", + "type": "String" + }, + { + "name": "event_sub_type", + "type": "String" + } + ] + }, + { + "name": "logs", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 605222628, + "return_value": { + "type": "POGRResponse" + }, + "arguments": [ + { + "name": "tags", + "type": "Dictionary" + }, + { + "name": "data", + "type": "Dictionary" + }, + { + "name": "environment", + "type": "String" + }, + { + "name": "log", + "type": "String" + }, + { + "name": "service", + "type": "String" + }, + { + "name": "severity", + "type": "String" + }, + { + "name": "type", + "type": "String" + } + ] + }, + { + "name": "metrics", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1554274282, + "return_value": { + "type": "POGRResponse" + }, + "arguments": [ + { + "name": "tags", + "type": "Dictionary" + }, + { + "name": "environment", + "type": "String" + }, + { + "name": "metrics", + "type": "Dictionary" + }, + { + "name": "service", + "type": "String" + } + ] + }, + { + "name": "monitor", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3646189709, + "return_value": { + "type": "POGRResponse" + }, + "arguments": [ + { + "name": "settings", + "type": "Dictionary" + } + ] + }, + { + "name": "get_client_id", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_build_id", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_pogr_url", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_session_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + } + ] + }, + { + "name": "POGRResponse", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "signals": [ + { + "name": "finished", + "arguments": [ + { + "name": "result", + "type": "POGRResult" + } + ] + } + ] + }, + { + "name": "POGRResult", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "methods": [ + { + "name": "has_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_result", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + } + ], + "properties": [ + { + "type": "String", + "name": "error", + "getter": "get_error" + }, + { + "type": "String", + "name": "result", + "getter": "get_result" + } + ] + }, { "name": "PackedDataContainer", "is_refcounted": true, @@ -178848,6 +183495,39 @@ } ] }, + { + "name": "space_step", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1794382983, + "arguments": [ + { + "name": "space", + "type": "RID" + }, + { + "name": "delta", + "type": "float", + "meta": "float" + } + ] + }, + { + "name": "space_flush_queries", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2722037293, + "arguments": [ + { + "name": "space", + "type": "RID" + } + ] + }, { "name": "space_set_param", "is_const": false, @@ -180551,6 +185231,41 @@ } ] }, + { + "name": "joint_set_enabled", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1265174801, + "arguments": [ + { + "name": "joint", + "type": "RID" + }, + { + "name": "enabled", + "type": "bool" + } + ] + }, + { + "name": "joint_is_enabled", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 4155700596, + "return_value": { + "type": "bool" + }, + "arguments": [ + { + "name": "joint", + "type": "RID" + } + ] + }, { "name": "joint_set_param", "is_const": false, @@ -180929,6 +185644,28 @@ "type": "enum::PhysicsServer2D.ProcessInfo" } ] + }, + { + "name": "space_get_last_process_info", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 452167182, + "return_value": { + "type": "int", + "meta": "int32" + }, + "arguments": [ + { + "name": "space", + "type": "RID" + }, + { + "name": "process_info", + "type": "enum::PhysicsServer2D.ProcessInfo" + } + ] } ] }, @@ -181195,6 +185932,37 @@ } ] }, + { + "name": "_space_step", + "is_const": false, + "is_static": false, + "is_vararg": false, + "is_virtual": true, + "arguments": [ + { + "name": "space", + "type": "RID" + }, + { + "name": "delta", + "type": "float", + "meta": "float" + } + ] + }, + { + "name": "_space_flush_queries", + "is_const": false, + "is_static": false, + "is_vararg": false, + "is_virtual": true, + "arguments": [ + { + "name": "space", + "type": "RID" + } + ] + }, { "name": "_space_set_param", "is_const": false, @@ -182985,6 +187753,39 @@ } ] }, + { + "name": "_joint_set_enabled", + "is_const": false, + "is_static": false, + "is_vararg": false, + "is_virtual": true, + "arguments": [ + { + "name": "joint", + "type": "RID" + }, + { + "name": "enabled", + "type": "bool" + } + ] + }, + { + "name": "_joint_is_enabled", + "is_const": true, + "is_static": false, + "is_vararg": false, + "is_virtual": true, + "return_value": { + "type": "bool" + }, + "arguments": [ + { + "name": "joint", + "type": "RID" + } + ] + }, { "name": "_joint_set_param", "is_const": false, @@ -183393,6 +188194,27 @@ } ] }, + { + "name": "_space_get_last_process_info", + "is_const": false, + "is_static": false, + "is_vararg": false, + "is_virtual": true, + "return_value": { + "type": "int", + "meta": "int32" + }, + "arguments": [ + { + "name": "space", + "type": "RID" + }, + { + "name": "process_info", + "type": "enum::PhysicsServer2D.ProcessInfo" + } + ] + }, { "name": "body_test_motion_is_excluding_body", "is_const": true, @@ -184436,6 +189258,39 @@ } ] }, + { + "name": "space_step", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1794382983, + "arguments": [ + { + "name": "space", + "type": "RID" + }, + { + "name": "delta", + "type": "float", + "meta": "float" + } + ] + }, + { + "name": "space_flush_queries", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2722037293, + "arguments": [ + { + "name": "space", + "type": "RID" + } + ] + }, { "name": "space_set_param", "is_const": false, @@ -186725,6 +191580,41 @@ } ] }, + { + "name": "joint_set_enabled", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1265174801, + "arguments": [ + { + "name": "joint", + "type": "RID" + }, + { + "name": "enabled", + "type": "bool" + } + ] + }, + { + "name": "joint_is_enabled", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 4155700596, + "return_value": { + "type": "bool" + }, + "arguments": [ + { + "name": "joint", + "type": "RID" + } + ] + }, { "name": "joint_make_pin", "is_const": false, @@ -187406,6 +192296,28 @@ "type": "enum::PhysicsServer3D.ProcessInfo" } ] + }, + { + "name": "space_get_last_process_info", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2576518499, + "return_value": { + "type": "int", + "meta": "int32" + }, + "arguments": [ + { + "name": "space", + "type": "RID" + }, + { + "name": "process_info", + "type": "enum::PhysicsServer3D.ProcessInfo" + } + ] } ] }, @@ -187678,6 +192590,37 @@ } ] }, + { + "name": "_space_step", + "is_const": false, + "is_static": false, + "is_vararg": false, + "is_virtual": true, + "arguments": [ + { + "name": "space", + "type": "RID" + }, + { + "name": "delta", + "type": "float", + "meta": "float" + } + ] + }, + { + "name": "_space_flush_queries", + "is_const": false, + "is_static": false, + "is_vararg": false, + "is_virtual": true, + "arguments": [ + { + "name": "space", + "type": "RID" + } + ] + }, { "name": "_space_set_param", "is_const": false, @@ -189998,6 +194941,39 @@ } ] }, + { + "name": "_joint_set_enabled", + "is_const": false, + "is_static": false, + "is_vararg": false, + "is_virtual": true, + "arguments": [ + { + "name": "joint", + "type": "RID" + }, + { + "name": "enabled", + "type": "bool" + } + ] + }, + { + "name": "_joint_is_enabled", + "is_const": true, + "is_static": false, + "is_vararg": false, + "is_virtual": true, + "return_value": { + "type": "bool" + }, + "arguments": [ + { + "name": "joint", + "type": "RID" + } + ] + }, { "name": "_joint_make_pin", "is_const": false, @@ -190745,6 +195721,27 @@ } ] }, + { + "name": "_space_get_last_process_info", + "is_const": false, + "is_static": false, + "is_vararg": false, + "is_virtual": true, + "return_value": { + "type": "int", + "meta": "int32" + }, + "arguments": [ + { + "name": "space", + "type": "RID" + }, + { + "name": "process_info", + "type": "enum::PhysicsServer3D.ProcessInfo" + } + ] + }, { "name": "body_test_motion_is_excluding_body", "is_const": true, @@ -231816,6 +236813,23 @@ "is_vararg": false, "is_virtual": true }, + { + "name": "_reload_scripts", + "is_const": false, + "is_static": false, + "is_vararg": false, + "is_virtual": true, + "arguments": [ + { + "name": "scripts", + "type": "Array" + }, + { + "name": "soft_reload", + "type": "bool" + } + ] + }, { "name": "_reload_tool_script", "is_const": false, @@ -231985,6 +236999,767 @@ } ] }, + { + "name": "ScriptedLobbyClient", + "is_refcounted": false, + "is_instantiable": true, + "inherits": "BlaziumClient", + "api_type": "core", + "methods": [ + { + "name": "set_server_url", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "server_url", + "type": "String" + } + ] + }, + { + "name": "get_server_url", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "set_reconnection_token", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "reconnection_token", + "type": "String" + } + ] + }, + { + "name": "get_reconnection_token", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "set_game_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "game_id", + "type": "String" + } + ] + }, + { + "name": "get_game_id", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2841200299, + "return_value": { + "type": "String" + } + }, + { + "name": "is_host", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2240911060, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_connected", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2240911060, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_lobby", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2759059446, + "return_value": { + "type": "LobbyInfo" + } + }, + { + "name": "get_peer", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 899568590, + "return_value": { + "type": "LobbyPeer" + } + }, + { + "name": "get_peers", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2915620761, + "return_value": { + "type": "typedarray::LobbyPeer" + } + }, + { + "name": "get_peer_data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2382534195, + "return_value": { + "type": "Dictionary" + } + }, + { + "name": "set_override_discord_path", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 83702148, + "arguments": [ + { + "name": "override_discord_path", + "type": "String" + } + ] + }, + { + "name": "get_override_discord_path", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "connect_to_lobby", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 402759040, + "return_value": { + "type": "LobbyResponse" + } + }, + { + "name": "disconnect_from_lobby", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 402759040, + "return_value": { + "type": "LobbyResponse" + } + }, + { + "name": "create_lobby", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1782804803, + "return_value": { + "type": "ViewLobbyResponse" + }, + "arguments": [ + { + "name": "title", + "type": "String" + }, + { + "name": "sealed", + "type": "bool" + }, + { + "name": "tags", + "type": "Dictionary", + "default_value": "{}" + }, + { + "name": "max_players", + "type": "int", + "meta": "int32", + "default_value": "4" + }, + { + "name": "password", + "type": "String", + "default_value": "\"\"" + } + ] + }, + { + "name": "join_lobby", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3724509716, + "return_value": { + "type": "ViewLobbyResponse" + }, + "arguments": [ + { + "name": "lobby_id", + "type": "String" + }, + { + "name": "password", + "type": "String", + "default_value": "\"\"" + } + ] + }, + { + "name": "leave_lobby", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 402759040, + "return_value": { + "type": "LobbyResponse" + } + }, + { + "name": "lobby_call", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3787630981, + "return_value": { + "type": "ScriptedLobbyResponse" + }, + "arguments": [ + { + "name": "method", + "type": "String" + }, + { + "name": "args", + "type": "Array", + "default_value": "[]" + } + ] + }, + { + "name": "list_lobbies", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 402759040, + "return_value": { + "type": "LobbyResponse" + } + }, + { + "name": "kick_peer", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3186253920, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "peer_id", + "type": "String" + } + ] + }, + { + "name": "send_chat_message", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3186253920, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "chat_message", + "type": "String" + } + ] + }, + { + "name": "set_lobby_ready", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 668034168, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "ready", + "type": "bool" + } + ] + }, + { + "name": "add_lobby_tags", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3614381552, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "tags", + "type": "Dictionary" + } + ] + }, + { + "name": "del_lobby_tags", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2785274044, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "keys", + "type": "typedarray::String" + } + ] + }, + { + "name": "set_lobby_sealed", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 668034168, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "seal", + "type": "bool" + } + ] + }, + { + "name": "add_peer_user_data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3614381552, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "data", + "type": "Dictionary" + } + ] + }, + { + "name": "del_peer_user_data", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2785274044, + "return_value": { + "type": "LobbyResponse" + }, + "arguments": [ + { + "name": "keys", + "type": "typedarray::String" + } + ] + } + ], + "signals": [ + { + "name": "connected_to_lobby", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + }, + { + "name": "reconnection_token", + "type": "String" + } + ] + }, + { + "name": "disconnected_from_lobby", + "arguments": [ + { + "name": "reason", + "type": "String" + } + ] + }, + { + "name": "received_peer_user_data", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + }, + { + "name": "data", + "type": "Object" + } + ] + }, + { + "name": "lobby_notified", + "arguments": [ + { + "name": "data", + "type": "Object" + } + ] + }, + { + "name": "received_peer_data", + "arguments": [ + { + "name": "data", + "type": "Object" + }, + { + "name": "to_peer", + "type": "LobbyPeer" + }, + { + "name": "is_private", + "type": "bool" + } + ] + }, + { + "name": "received_lobby_data", + "arguments": [ + { + "name": "data", + "type": "Object" + } + ] + }, + { + "name": "lobby_created", + "arguments": [ + { + "name": "lobby", + "type": "LobbyInfo" + }, + { + "name": "peers", + "type": "typedarray::LobbyPeer" + } + ] + }, + { + "name": "lobby_joined", + "arguments": [ + { + "name": "lobby", + "type": "LobbyInfo" + }, + { + "name": "peers", + "type": "typedarray::LobbyPeer" + } + ] + }, + { + "name": "lobby_left", + "arguments": [ + { + "name": "kicked", + "type": "bool" + } + ] + }, + { + "name": "lobby_sealed", + "arguments": [ + { + "name": "sealed", + "type": "bool" + } + ] + }, + { + "name": "lobby_tagged", + "arguments": [ + { + "name": "tags", + "type": "Dictionary" + } + ] + }, + { + "name": "lobbies_listed", + "arguments": [ + { + "name": "lobbies", + "type": "typedarray::LobbyInfo" + } + ] + }, + { + "name": "peer_joined", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + } + ] + }, + { + "name": "peer_reconnected", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + } + ] + }, + { + "name": "peer_left", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + }, + { + "name": "kicked", + "type": "bool" + } + ] + }, + { + "name": "peer_disconnected", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + } + ] + }, + { + "name": "peer_messaged", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + }, + { + "name": "chat_message", + "type": "String" + } + ] + }, + { + "name": "peer_ready", + "arguments": [ + { + "name": "peer", + "type": "LobbyPeer" + }, + { + "name": "is_ready", + "type": "bool" + } + ] + }, + { + "name": "log_updated", + "arguments": [ + { + "name": "command", + "type": "String" + }, + { + "name": "logs", + "type": "String" + } + ] + } + ], + "properties": [ + { + "type": "String", + "name": "server_url", + "setter": "set_server_url", + "getter": "get_server_url" + }, + { + "type": "String", + "name": "reconnection_token", + "setter": "set_reconnection_token", + "getter": "get_reconnection_token" + }, + { + "type": "String", + "name": "game_id", + "setter": "set_game_id", + "getter": "get_game_id" + }, + { + "type": "bool", + "name": "connected", + "getter": "get_connected" + }, + { + "type": "LobbyInfo", + "name": "lobby", + "getter": "get_lobby" + }, + { + "type": "LobbyPeer", + "name": "peer", + "getter": "get_peer" + }, + { + "type": "typedarray::LobbyPeer", + "name": "peers", + "getter": "get_peers" + }, + { + "type": "Dictionary", + "name": "peer_data", + "getter": "get_peer_data" + } + ] + }, + { + "name": "ScriptedLobbyResponse", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "signals": [ + { + "name": "finished", + "arguments": [ + { + "name": "result", + "type": "ScriptedLobbyResult" + } + ] + } + ] + }, + { + "name": "ScriptedLobbyResult", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "methods": [ + { + "name": "has_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_result", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1214101251, + "return_value": { + "type": "Variant" + } + } + ], + "properties": [ + { + "type": "String", + "name": "error", + "getter": "get_error" + } + ] + }, { "name": "ScrollBar", "is_refcounted": false, @@ -240513,6 +246288,28 @@ "value": 2 } ] + }, + { + "name": "CollapseMode", + "is_bitfield": false, + "values": [ + { + "name": "COLLAPSE_NONE", + "value": 0 + }, + { + "name": "COLLAPSE_FIRST", + "value": 1 + }, + { + "name": "COLLAPSE_SECOND", + "value": 2 + }, + { + "name": "COLLAPSE_ALL", + "value": 3 + } + ] } ], "methods": [ @@ -240543,14 +246340,6 @@ "meta": "int32" } }, - { - "name": "clamp_split_offset", - "is_const": false, - "is_vararg": false, - "is_static": false, - "is_virtual": false, - "hash": 3218959716 - }, { "name": "set_collapsed", "is_const": false, @@ -240625,6 +246414,100 @@ "return_value": { "type": "bool" } + }, + { + "name": "set_collapse_mode", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 460731385, + "arguments": [ + { + "name": "mode", + "type": "enum::SplitContainer.CollapseMode" + } + ] + }, + { + "name": "get_collapse_mode", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3853120500, + "return_value": { + "type": "enum::SplitContainer.CollapseMode" + } + }, + { + "name": "set_drag_area_highlight_in_editor", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2586408642, + "arguments": [ + { + "name": "drag_area_highlight_in_editor", + "type": "bool" + } + ] + }, + { + "name": "is_drag_area_highlight_in_editor_enabled", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "set_dragging_enabled", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2586408642, + "arguments": [ + { + "name": "dragging_enabled", + "type": "bool" + } + ] + }, + { + "name": "is_dragging_enabled", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_drag_area_control", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2783021301, + "return_value": { + "type": "Control" + } + }, + { + "name": "clamp_split_offset", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3218959716 } ], "signals": [ @@ -240636,9 +246519,21 @@ "type": "int" } ] + }, + { + "name": "drag_started" + }, + { + "name": "drag_ended" } ], "properties": [ + { + "type": "bool", + "name": "dragging_enabled", + "setter": "set_dragging_enabled", + "getter": "is_dragging_enabled" + }, { "type": "int", "name": "split_offset", @@ -240662,6 +246557,18 @@ "name": "vertical", "setter": "set_vertical", "getter": "is_vertical" + }, + { + "type": "int", + "name": "collapse_mode", + "setter": "set_collapse_mode", + "getter": "get_collapse_mode" + }, + { + "type": "bool", + "name": "drag_area_highlight_in_editor", + "setter": "set_drag_area_highlight_in_editor", + "getter": "is_drag_area_highlight_in_editor_enabled" } ] }, @@ -246559,6 +252466,31 @@ "type": "enum::TextServer.SubpixelPositioning" } }, + { + "name": "set_lcd_subpixel_layout", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1893246148, + "arguments": [ + { + "name": "subpixel_layout", + "type": "enum::TextServer.FontLCDSubpixelLayout" + } + ] + }, + { + "name": "get_lcd_subpixel_layout", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 1912389403, + "return_value": { + "type": "enum::TextServer.FontLCDSubpixelLayout" + } + }, { "name": "set_multichannel_signed_distance_field", "is_const": false, @@ -246813,6 +252745,12 @@ "setter": "set_subpixel_positioning", "getter": "get_subpixel_positioning" }, + { + "type": "int", + "name": "lcd_subpixel_layout", + "setter": "set_lcd_subpixel_layout", + "getter": "get_lcd_subpixel_layout" + }, { "type": "bool", "name": "multichannel_signed_distance_field", @@ -256700,6 +262638,41 @@ } ] }, + { + "name": "font_set_lcd_subpixel_layout", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 2980830814, + "arguments": [ + { + "name": "font_rid", + "type": "RID" + }, + { + "name": "lcd_subpixel_layout", + "type": "enum::TextServer.FontLCDSubpixelLayout" + } + ] + }, + { + "name": "font_get_lcd_subpixel_layout", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3925881174, + "return_value": { + "type": "enum::TextServer.FontLCDSubpixelLayout" + }, + "arguments": [ + { + "name": "font_rid", + "type": "RID" + } + ] + }, { "name": "font_set_disable_embedded_bitmaps", "is_const": false, @@ -261242,6 +267215,39 @@ } ] }, + { + "name": "_font_set_lcd_subpixel_layout", + "is_const": false, + "is_static": false, + "is_vararg": false, + "is_virtual": true, + "arguments": [ + { + "name": "font_rid", + "type": "RID" + }, + { + "name": "subpixel_layout", + "type": "enum::TextServer.FontLCDSubpixelLayout" + } + ] + }, + { + "name": "_font_get_lcd_subpixel_layout", + "is_const": true, + "is_static": false, + "is_vararg": false, + "is_virtual": true, + "return_value": { + "type": "enum::TextServer.FontLCDSubpixelLayout" + }, + "arguments": [ + { + "name": "font_rid", + "type": "RID" + } + ] + }, { "name": "_font_set_disable_embedded_bitmaps", "is_const": false, @@ -268517,6 +274523,9 @@ "signals": [ { "name": "fallback_changed" + }, + { + "name": "icons_changed" } ], "properties": [ @@ -268552,6 +274561,13 @@ } ] }, + { + "name": "ThirdPartyClient", + "is_refcounted": false, + "is_instantiable": false, + "inherits": "Node", + "api_type": "core" + }, { "name": "Thread", "is_refcounted": true, @@ -278231,6 +284247,43 @@ } ] }, + { + "name": "set_icon_overlay", + "is_const": false, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 666127730, + "arguments": [ + { + "name": "column", + "type": "int", + "meta": "int32" + }, + { + "name": "texture", + "type": "Texture2D" + } + ] + }, + { + "name": "get_icon_overlay", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3536238170, + "return_value": { + "type": "Texture2D" + }, + "arguments": [ + { + "name": "column", + "type": "int", + "meta": "int32" + } + ] + }, { "name": "set_icon_region", "is_const": false, @@ -283221,6 +289274,94 @@ "inherits": "VideoStream", "api_type": "core" }, + { + "name": "ViewLobbyResponse", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "signals": [ + { + "name": "finished", + "arguments": [ + { + "name": "result", + "type": "ViewLobbyResult" + } + ] + } + ] + }, + { + "name": "ViewLobbyResult", + "is_refcounted": true, + "is_instantiable": true, + "inherits": "RefCounted", + "api_type": "core", + "methods": [ + { + "name": "has_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 36873697, + "return_value": { + "type": "bool" + } + }, + { + "name": "get_error", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 201670096, + "return_value": { + "type": "String" + } + }, + { + "name": "get_peers", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 3995934104, + "return_value": { + "type": "typedarray::LobbyPeer" + } + }, + { + "name": "get_lobby", + "is_const": true, + "is_vararg": false, + "is_static": false, + "is_virtual": false, + "hash": 111667471, + "return_value": { + "type": "LobbyInfo" + } + } + ], + "properties": [ + { + "type": "typedarray::LobbyPeer", + "name": "peers", + "getter": "get_peers" + }, + { + "type": "LobbyInfo", + "name": "lobby", + "getter": "get_lobby" + }, + { + "type": "String", + "name": "error", + "getter": "get_error" + } + ] + }, { "name": "Viewport", "is_refcounted": false, @@ -304195,6 +310336,10 @@ "name": "Performance", "type": "Performance" }, + { + "name": "JWT", + "type": "JWT" + }, { "name": "TextServerManager", "type": "TextServerManager" @@ -304398,4 +310543,4 @@ "format": "StringName signature;uint64_t call_count;uint64_t total_time;uint64_t self_time" } ] -} +} \ No newline at end of file diff --git a/include/godot_cpp/core/math.hpp b/include/godot_cpp/core/math.hpp index 1949360a9..d099c2d95 100644 --- a/include/godot_cpp/core/math.hpp +++ b/include/godot_cpp/core/math.hpp @@ -538,6 +538,26 @@ inline float bezier_interpolate(float p_start, float p_control_1, float p_contro return p_start * omt3 + p_control_1 * omt2 * p_t * 3.0f + p_control_2 * omt * t2 * 3.0f + p_end * t3; } +static inline double bezier_derivative(double p_start, double p_control_1, double p_control_2, double p_end, double p_t) { + /* Formula from Wikipedia article on Bezier curves. */ + double omt = (1.0 - p_t); + double omt2 = omt * omt; + double t2 = p_t * p_t; + + double d = (p_control_1 - p_start) * 3.0 * omt2 + (p_control_2 - p_control_1) * 6.0 * omt * p_t + (p_end - p_control_2) * 3.0 * t2; + return d; +} + +static inline float bezier_derivative(float p_start, float p_control_1, float p_control_2, float p_end, float p_t) { + /* Formula from Wikipedia article on Bezier curves. */ + float omt = (1.0f - p_t); + float omt2 = omt * omt; + float t2 = p_t * p_t; + + float d = (p_control_1 - p_start) * 3.0f * omt2 + (p_control_2 - p_control_1) * 6.0f * omt * p_t + (p_end - p_control_2) * 3.0f * t2; + return d; +} + template inline T clamp(T x, T minv, T maxv) { if (x < minv) { diff --git a/include/godot_cpp/variant/aabb.hpp b/include/godot_cpp/variant/aabb.hpp index b827112af..e26c05f56 100644 --- a/include/godot_cpp/variant/aabb.hpp +++ b/include/godot_cpp/variant/aabb.hpp @@ -41,6 +41,11 @@ namespace godot { +/** + * AABB (Axis Aligned Bounding Box) + * This is implemented by a point (position) and the box size. + */ + class Variant; struct _NO_DISCARD_ AABB { @@ -73,9 +78,14 @@ struct _NO_DISCARD_ AABB { AABB merge(const AABB &p_with) const; void merge_with(const AABB &p_aabb); ///merge with another AABB AABB intersection(const AABB &p_aabb) const; ///get box where two intersect, empty if no intersection occurs - bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const; - bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const; - _FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const; + _FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t p_t0, real_t p_t1) const; + + bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_intersection_point = nullptr, Vector3 *r_normal = nullptr) const; + bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir) const { + bool inside; + return find_intersects_ray(p_from, p_dir, inside); + } + bool find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool &r_inside, Vector3 *r_intersection_point = nullptr, Vector3 *r_normal = nullptr) const; _FORCE_INLINE_ bool intersects_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const; _FORCE_INLINE_ bool inside_convex_shape(const Plane *p_planes, int p_plane_count) const; @@ -403,7 +413,7 @@ inline real_t AABB::get_shortest_axis_size() const { return max_size; } -bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const { +bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t p_t0, real_t p_t1) const { #ifdef MATH_CHECKS if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) { ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size."); @@ -454,7 +464,7 @@ bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real if (tzmax < tmax) { tmax = tzmax; } - return ((tmin < t1) && (tmax > t0)); + return ((tmin < p_t1) && (tmax > p_t0)); } void AABB::grow_by(real_t p_amount) { diff --git a/include/godot_cpp/variant/basis.hpp b/include/godot_cpp/variant/basis.hpp index f3ebe15fe..db52ac440 100644 --- a/include/godot_cpp/variant/basis.hpp +++ b/include/godot_cpp/variant/basis.hpp @@ -44,11 +44,11 @@ struct _NO_DISCARD_ Basis { Vector3(0, 0, 1) }; - _FORCE_INLINE_ const Vector3 &operator[](int axis) const { - return rows[axis]; + _FORCE_INLINE_ const Vector3 &operator[](int p_row) const { + return rows[p_row]; } - _FORCE_INLINE_ Vector3 &operator[](int axis) { - return rows[axis]; + _FORCE_INLINE_ Vector3 &operator[](int p_row) { + return rows[p_row]; } void invert(); @@ -59,8 +59,6 @@ struct _NO_DISCARD_ Basis { _FORCE_INLINE_ real_t determinant() const; - void from_z(const Vector3 &p_z); - void rotate(const Vector3 &p_axis, real_t p_angle); Basis rotated(const Vector3 &p_axis, real_t p_angle) const; @@ -104,27 +102,25 @@ struct _NO_DISCARD_ Basis { void scale_orthogonal(const Vector3 &p_scale); Basis scaled_orthogonal(const Vector3 &p_scale) const; - - void make_scale_uniform(); - float get_uniform_scale() const; + real_t get_uniform_scale() const; Vector3 get_scale() const; Vector3 get_scale_abs() const; - Vector3 get_scale_local() const; + Vector3 get_scale_global() const; void set_axis_angle_scale(const Vector3 &p_axis, real_t p_angle, const Vector3 &p_scale); void set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale, EulerOrder p_order = EULER_ORDER_YXZ); void set_quaternion_scale(const Quaternion &p_quaternion, const Vector3 &p_scale); // transposed dot products - _FORCE_INLINE_ real_t tdotx(const Vector3 &v) const { - return rows[0][0] * v[0] + rows[1][0] * v[1] + rows[2][0] * v[2]; + _FORCE_INLINE_ real_t tdotx(const Vector3 &p_v) const { + return rows[0][0] * p_v[0] + rows[1][0] * p_v[1] + rows[2][0] * p_v[2]; } - _FORCE_INLINE_ real_t tdoty(const Vector3 &v) const { - return rows[0][1] * v[0] + rows[1][1] * v[1] + rows[2][1] * v[2]; + _FORCE_INLINE_ real_t tdoty(const Vector3 &p_v) const { + return rows[0][1] * p_v[0] + rows[1][1] * p_v[1] + rows[2][1] * p_v[2]; } - _FORCE_INLINE_ real_t tdotz(const Vector3 &v) const { - return rows[0][2] * v[0] + rows[1][2] * v[1] + rows[2][2] * v[2]; + _FORCE_INLINE_ real_t tdotz(const Vector3 &p_v) const { + return rows[0][2] * p_v[0] + rows[1][2] * p_v[1] + rows[2][2] * p_v[2]; } bool is_equal_approx(const Basis &p_basis) const; @@ -143,8 +139,12 @@ struct _NO_DISCARD_ Basis { _FORCE_INLINE_ Basis operator-(const Basis &p_matrix) const; _FORCE_INLINE_ void operator*=(const real_t p_val); _FORCE_INLINE_ Basis operator*(const real_t p_val) const; + _FORCE_INLINE_ void operator/=(const real_t p_val); + _FORCE_INLINE_ Basis operator/(const real_t p_val) const; bool is_orthogonal() const; + bool is_orthonormal() const; + bool is_conformal() const; bool is_diagonal() const; bool is_rotation() const; @@ -156,16 +156,16 @@ struct _NO_DISCARD_ Basis { /* create / set */ - _FORCE_INLINE_ void set(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) { - rows[0][0] = xx; - rows[0][1] = xy; - rows[0][2] = xz; - rows[1][0] = yx; - rows[1][1] = yy; - rows[1][2] = yz; - rows[2][0] = zx; - rows[2][1] = zy; - rows[2][2] = zz; + _FORCE_INLINE_ void set(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz) { + rows[0][0] = p_xx; + rows[0][1] = p_xy; + rows[0][2] = p_xz; + rows[1][0] = p_yx; + rows[1][1] = p_yy; + rows[1][2] = p_yz; + rows[2][0] = p_zx; + rows[2][1] = p_zy; + rows[2][2] = p_zz; } _FORCE_INLINE_ void set_columns(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z) { set_column(0, p_x); @@ -195,20 +195,20 @@ struct _NO_DISCARD_ Basis { rows[2].zero(); } - _FORCE_INLINE_ Basis transpose_xform(const Basis &m) const { + _FORCE_INLINE_ Basis transpose_xform(const Basis &p_m) const { return Basis( - rows[0].x * m[0].x + rows[1].x * m[1].x + rows[2].x * m[2].x, - rows[0].x * m[0].y + rows[1].x * m[1].y + rows[2].x * m[2].y, - rows[0].x * m[0].z + rows[1].x * m[1].z + rows[2].x * m[2].z, - rows[0].y * m[0].x + rows[1].y * m[1].x + rows[2].y * m[2].x, - rows[0].y * m[0].y + rows[1].y * m[1].y + rows[2].y * m[2].y, - rows[0].y * m[0].z + rows[1].y * m[1].z + rows[2].y * m[2].z, - rows[0].z * m[0].x + rows[1].z * m[1].x + rows[2].z * m[2].x, - rows[0].z * m[0].y + rows[1].z * m[1].y + rows[2].z * m[2].y, - rows[0].z * m[0].z + rows[1].z * m[1].z + rows[2].z * m[2].z); + rows[0].x * p_m[0].x + rows[1].x * p_m[1].x + rows[2].x * p_m[2].x, + rows[0].x * p_m[0].y + rows[1].x * p_m[1].y + rows[2].x * p_m[2].y, + rows[0].x * p_m[0].z + rows[1].x * p_m[1].z + rows[2].x * p_m[2].z, + rows[0].y * p_m[0].x + rows[1].y * p_m[1].x + rows[2].y * p_m[2].x, + rows[0].y * p_m[0].y + rows[1].y * p_m[1].y + rows[2].y * p_m[2].y, + rows[0].y * p_m[0].z + rows[1].y * p_m[1].z + rows[2].y * p_m[2].z, + rows[0].z * p_m[0].x + rows[1].z * p_m[1].x + rows[2].z * p_m[2].x, + rows[0].z * p_m[0].y + rows[1].z * p_m[1].y + rows[2].z * p_m[2].y, + rows[0].z * p_m[0].z + rows[1].z * p_m[1].z + rows[2].z * p_m[2].z); } - Basis(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) { - set(xx, xy, xz, yx, yy, yz, zx, zy, zz); + Basis(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz) { + set(p_xx, p_xy, p_xz, p_yx, p_yy, p_yz, p_zx, p_zy, p_zz); } void orthonormalize(); @@ -294,6 +294,18 @@ _FORCE_INLINE_ Basis Basis::operator*(const real_t p_val) const { return ret; } +_FORCE_INLINE_ void Basis::operator/=(const real_t p_val) { + rows[0] /= p_val; + rows[1] /= p_val; + rows[2] /= p_val; +} + +_FORCE_INLINE_ Basis Basis::operator/(const real_t p_val) const { + Basis ret(*this); + ret /= p_val; + return ret; +} + Vector3 Basis::xform(const Vector3 &p_vector) const { return Vector3( rows[0].dot(p_vector), diff --git a/include/godot_cpp/variant/color.hpp b/include/godot_cpp/variant/color.hpp index 0e837bc9f..6dea2c351 100644 --- a/include/godot_cpp/variant/color.hpp +++ b/include/godot_cpp/variant/color.hpp @@ -59,6 +59,10 @@ struct _NO_DISCARD_ Color { float get_s() const; float get_v() const; void set_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0f); + float get_ok_hsl_h() const; + float get_ok_hsl_s() const; + float get_ok_hsl_l() const; + void set_ok_hsl(float p_h, float p_s, float p_l, float p_alpha = 1.0f); _FORCE_INLINE_ float &operator[](int p_idx) { return components[p_idx]; @@ -103,12 +107,10 @@ struct _NO_DISCARD_ Color { _FORCE_INLINE_ Color lerp(const Color &p_to, float p_weight) const { Color res = *this; - - 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)); - + res.r = Math::lerp(res.r, p_to.r, p_weight); + res.g = Math::lerp(res.g, p_to.g, p_weight); + res.b = Math::lerp(res.b, p_to.b, p_weight); + res.a = Math::lerp(res.a, p_to.a, p_weight); return res; } @@ -129,33 +131,46 @@ struct _NO_DISCARD_ Color { } _FORCE_INLINE_ uint32_t to_rgbe9995() const { - const float pow2to9 = 512.0f; - const float B = 15.0f; - const float N = 9.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)); - float cBlue = MAX(0.0f, MIN(sharedexp, b)); - - float cMax = MAX(cRed, MAX(cGreen, cBlue)); - - float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / (real_t)Math_LN2)) + 1.0f + B; - - float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f); - - float exps = expp + 1.0f; - - if (0.0f <= sMax && sMax < pow2to9) { - exps = expp; - } - - float sRed = Math::floor((cRed / pow(2.0f, exps - B - N)) + 0.5f); - float sGreen = Math::floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f); - float sBlue = Math::floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f); - - return (uint32_t(Math::fast_ftoi(sRed)) & 0x1FF) | ((uint32_t(Math::fast_ftoi(sGreen)) & 0x1FF) << 9) | ((uint32_t(Math::fast_ftoi(sBlue)) & 0x1FF) << 18) | ((uint32_t(Math::fast_ftoi(exps)) & 0x1F) << 27); + // https://github.com/microsoft/DirectX-Graphics-Samples/blob/v10.0.19041.0/MiniEngine/Core/Color.cpp + static const float kMaxVal = float(0x1FF << 7); + static const float kMinVal = float(1.f / (1 << 16)); + + // Clamp RGB to [0, 1.FF*2^16] + const float _r = CLAMP(r, 0.0f, kMaxVal); + const float _g = CLAMP(g, 0.0f, kMaxVal); + const float _b = CLAMP(b, 0.0f, kMaxVal); + + // Compute the maximum channel, no less than 1.0*2^-15 + const float MaxChannel = MAX(MAX(_r, _g), MAX(_b, kMinVal)); + + // Take the exponent of the maximum channel (rounding up the 9th bit) and + // add 15 to it. When added to the channels, it causes the implicit '1.0' + // bit and the first 8 mantissa bits to be shifted down to the low 9 bits + // of the mantissa, rounding the truncated bits. + union { + float f; + int32_t i; + } R, G, B, E; + + E.f = MaxChannel; + E.i += 0x07804000; // Add 15 to the exponent and 0x4000 to the mantissa + E.i &= 0x7F800000; // Zero the mantissa + + // This shifts the 9-bit values we need into the lowest bits, rounding as + // needed. Note that if the channel has a smaller exponent than the max + // channel, it will shift even more. This is intentional. + R.f = _r + E.f; + G.f = _g + E.f; + B.f = _b + E.f; + + // Convert the Bias to the correct exponent in the upper 5 bits. + E.i <<= 4; + E.i += 0x10000000; + + // Combine the fields. RGB floats have unwanted data in the upper 9 + // bits. Only red needs to mask them off because green and blue shift + // it out to the left. + return E.i | (B.i << 18) | (G.i << 9) | (R.i & 511); } _FORCE_INLINE_ Color blend(const Color &p_over) const { @@ -174,16 +189,16 @@ struct _NO_DISCARD_ Color { _FORCE_INLINE_ Color srgb_to_linear() const { return Color( - r < 0.04045f ? r * (1.0f / 12.92f) : Math::pow((r + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f), - g < 0.04045f ? g * (1.0f / 12.92f) : Math::pow((g + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f), - b < 0.04045f ? b * (1.0f / 12.92f) : Math::pow((b + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f), + r < 0.04045f ? r * (1.0f / 12.92f) : Math::pow(float((r + 0.055) * (1.0 / (1.0 + 0.055))), 2.4f), + g < 0.04045f ? g * (1.0f / 12.92f) : Math::pow(float((g + 0.055) * (1.0 / (1.0 + 0.055))), 2.4f), + b < 0.04045f ? b * (1.0f / 12.92f) : Math::pow(float((b + 0.055) * (1.0 / (1.0 + 0.055))), 2.4f), a); } _FORCE_INLINE_ Color linear_to_srgb() const { return Color( - r < 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * Math::pow(r, 1.0f / 2.4f) - 0.055f, - g < 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * Math::pow(g, 1.0f / 2.4f) - 0.055f, - b < 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * Math::pow(b, 1.0f / 2.4f) - 0.055f, a); + r < 0.0031308f ? 12.92f * r : (1.0 + 0.055) * Math::pow(r, 1.0f / 2.4f) - 0.055, + g < 0.0031308f ? 12.92f * g : (1.0 + 0.055) * Math::pow(g, 1.0f / 2.4f) - 0.055, + b < 0.0031308f ? 12.92f * b : (1.0 + 0.055) * Math::pow(b, 1.0f / 2.4f) - 0.055, a); } static Color hex(uint32_t p_hex); @@ -198,6 +213,7 @@ struct _NO_DISCARD_ Color { static Color get_named_color(int p_idx); static Color from_string(const String &p_string, const Color &p_default); static Color from_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0f); + static Color from_ok_hsl(float p_h, float p_s, float p_l, float p_alpha = 1.0f); static Color from_rgbe9995(uint32_t p_rgbe); _FORCE_INLINE_ bool operator<(const Color &p_color) const; // Used in set keys. @@ -216,6 +232,9 @@ struct _NO_DISCARD_ Color { _FORCE_INLINE_ void set_h(float p_h) { set_hsv(p_h, get_s(), get_v(), a); } _FORCE_INLINE_ void set_s(float p_s) { set_hsv(get_h(), p_s, get_v(), a); } _FORCE_INLINE_ void set_v(float p_v) { set_hsv(get_h(), get_s(), p_v, a); } + _FORCE_INLINE_ void set_ok_hsl_h(float p_h) { set_ok_hsl(p_h, get_ok_hsl_s(), get_ok_hsl_l(), a); } + _FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l(), a); } + _FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l, a); } _FORCE_INLINE_ Color() {} diff --git a/include/godot_cpp/variant/ok_color.hpp b/include/godot_cpp/variant/ok_color.hpp new file mode 100644 index 000000000..6d2c39d0d --- /dev/null +++ b/include/godot_cpp/variant/ok_color.hpp @@ -0,0 +1,674 @@ +// Copyright(c) 2021 Björn Ottosson +// +// 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 GODOT_OK_COLOR_HPP + #define GODOT_OK_COLOR_HPP +#include +#include + + namespace godot { + + class ok_color { + public: + struct Lab { + float L; + float a; + float b; + }; + struct RGB { + float r; + float g; + float b; + }; + struct HSV { + float h; + float s; + float v; + }; + struct HSL { + float h; + float s; + float l; + }; + struct LC { + float L; + float C; + }; + + // Alternative representation of (L_cusp, C_cusp) + // Encoded so S = C_cusp/L_cusp and T = C_cusp/(1-L_cusp) + // The maximum value for C in the triangle is then found as fmin(S*L, T*(1-L)), for a given L + struct ST { + float S; + float T; + }; + + static constexpr float pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062f; + + static float clamp(float x, float min, float max) { + if (x < min) + return min; + if (x > max) + return max; + + return x; + } + + static float sgn(float x) { + return (float)(0.f < x) - (float)(x < 0.f); + } + + static float srgb_transfer_function(float a) { + return .0031308f >= a ? 12.92f * a : 1.055f * powf(a, .4166666666666667f) - .055f; + } + + static float srgb_transfer_function_inv(float a) { + return .04045f < a ? powf((a + .055f) / 1.055f, 2.4f) : a / 12.92f; + } + + static Lab linear_srgb_to_oklab(RGB c) { + float l = 0.4122214708f * c.r + 0.5363325363f * c.g + 0.0514459929f * c.b; + float m = 0.2119034982f * c.r + 0.6806995451f * c.g + 0.1073969566f * c.b; + float s = 0.0883024619f * c.r + 0.2817188376f * c.g + 0.6299787005f * c.b; + + float l_ = cbrtf(l); + float m_ = cbrtf(m); + float s_ = cbrtf(s); + + return { + 0.2104542553f * l_ + 0.7936177850f * m_ - 0.0040720468f * s_, + 1.9779984951f * l_ - 2.4285922050f * m_ + 0.4505937099f * s_, + 0.0259040371f * l_ + 0.7827717662f * m_ - 0.8086757660f * s_, + }; + } + + static RGB oklab_to_linear_srgb(Lab c) { + float l_ = c.L + 0.3963377774f * c.a + 0.2158037573f * c.b; + float m_ = c.L - 0.1055613458f * c.a - 0.0638541728f * c.b; + float s_ = c.L - 0.0894841775f * c.a - 1.2914855480f * c.b; + + float l = l_ * l_ * l_; + float m = m_ * m_ * m_; + float s = s_ * s_ * s_; + + return { + +4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s, + -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s, + -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s, + }; + } + + // Finds the maximum saturation possible for a given hue that fits in sRGB + // Saturation here is defined as S = C/L + // a and b must be normalized so a^2 + b^2 == 1 + static float compute_max_saturation(float a, float b) { + // Max saturation will be when one of r, g or b goes below zero. + + // Select different coefficients depending on which component goes below zero first + float k0, k1, k2, k3, k4, wl, wm, ws; + + if (-1.88170328f * a - 0.80936493f * b > 1) { + // Red component + k0 = +1.19086277f; + k1 = +1.76576728f; + k2 = +0.59662641f; + k3 = +0.75515197f; + k4 = +0.56771245f; + wl = +4.0767416621f; + wm = -3.3077115913f; + ws = +0.2309699292f; + } else if (1.81444104f * a - 1.19445276f * b > 1) { + // Green component + k0 = +0.73956515f; + k1 = -0.45954404f; + k2 = +0.08285427f; + k3 = +0.12541070f; + k4 = +0.14503204f; + wl = -1.2684380046f; + wm = +2.6097574011f; + ws = -0.3413193965f; + } else { + // Blue component + k0 = +1.35733652f; + k1 = -0.00915799f; + k2 = -1.15130210f; + k3 = -0.50559606f; + k4 = +0.00692167f; + wl = -0.0041960863f; + wm = -0.7034186147f; + ws = +1.7076147010f; + } + + // Approximate max saturation using a polynomial: + float S = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b; + + // Do one step Halley's method to get closer + // this gives an error less than 10e6, except for some blue hues where the dS/dh is close to infinite + // this should be sufficient for most applications, otherwise do two/three steps + + float k_l = +0.3963377774f * a + 0.2158037573f * b; + float k_m = -0.1055613458f * a - 0.0638541728f * b; + float k_s = -0.0894841775f * a - 1.2914855480f * b; + + { + float l_ = 1.f + S * k_l; + float m_ = 1.f + S * k_m; + float s_ = 1.f + S * k_s; + + float l = l_ * l_ * l_; + float m = m_ * m_ * m_; + float s = s_ * s_ * s_; + + float l_dS = 3.f * k_l * l_ * l_; + float m_dS = 3.f * k_m * m_ * m_; + float s_dS = 3.f * k_s * s_ * s_; + + float l_dS2 = 6.f * k_l * k_l * l_; + float m_dS2 = 6.f * k_m * k_m * m_; + float s_dS2 = 6.f * k_s * k_s * s_; + + float f = wl * l + wm * m + ws * s; + float f1 = wl * l_dS + wm * m_dS + ws * s_dS; + float f2 = wl * l_dS2 + wm * m_dS2 + ws * s_dS2; + + S = S - f * f1 / (f1 * f1 - 0.5f * f * f2); + } + + return S; + } + + // finds L_cusp and C_cusp for a given hue + // a and b must be normalized so a^2 + b^2 == 1 + static LC find_cusp(float a, float b) { + // First, find the maximum saturation (saturation S = C/L) + float S_cusp = compute_max_saturation(a, b); + + // Convert to linear sRGB to find the first point where at least one of r,g or b >= 1: + RGB rgb_at_max = oklab_to_linear_srgb({ 1, S_cusp * a, S_cusp * b }); + float L_cusp = cbrtf(1.f / fmax(fmax(rgb_at_max.r, rgb_at_max.g), rgb_at_max.b)); + float C_cusp = L_cusp * S_cusp; + + return { L_cusp, C_cusp }; + } + + // Finds intersection of the line defined by + // L = L0 * (1 - t) + t * L1; + // C = t * C1; + // a and b must be normalized so a^2 + b^2 == 1 + static float find_gamut_intersection(float a, float b, float L1, float C1, float L0, LC cusp) { + // Find the intersection for upper and lower half separately + float t; + if (((L1 - L0) * cusp.C - (cusp.L - L0) * C1) <= 0.f) { + // Lower half + + t = cusp.C * L0 / (C1 * cusp.L + cusp.C * (L0 - L1)); + } else { + // Upper half + + // First intersect with triangle + t = cusp.C * (L0 - 1.f) / (C1 * (cusp.L - 1.f) + cusp.C * (L0 - L1)); + + // Then one step Halley's method + { + float dL = L1 - L0; + float dC = C1; + + float k_l = +0.3963377774f * a + 0.2158037573f * b; + float k_m = -0.1055613458f * a - 0.0638541728f * b; + float k_s = -0.0894841775f * a - 1.2914855480f * b; + + float l_dt = dL + dC * k_l; + float m_dt = dL + dC * k_m; + float s_dt = dL + dC * k_s; + + // If higher accuracy is required, 2 or 3 iterations of the following block can be used: + { + float L = L0 * (1.f - t) + t * L1; + float C = t * C1; + + float l_ = L + C * k_l; + float m_ = L + C * k_m; + float s_ = L + C * k_s; + + float l = l_ * l_ * l_; + float m = m_ * m_ * m_; + float s = s_ * s_ * s_; + + float ldt = 3 * l_dt * l_ * l_; + float mdt = 3 * m_dt * m_ * m_; + float sdt = 3 * s_dt * s_ * s_; + + float ldt2 = 6 * l_dt * l_dt * l_; + float mdt2 = 6 * m_dt * m_dt * m_; + float sdt2 = 6 * s_dt * s_dt * s_; + + float r = 4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s - 1; + float r1 = 4.0767416621f * ldt - 3.3077115913f * mdt + 0.2309699292f * sdt; + float r2 = 4.0767416621f * ldt2 - 3.3077115913f * mdt2 + 0.2309699292f * sdt2; + + float u_r = r1 / (r1 * r1 - 0.5f * r * r2); + float t_r = -r * u_r; + + float g = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s - 1; + float g1 = -1.2684380046f * ldt + 2.6097574011f * mdt - 0.3413193965f * sdt; + float g2 = -1.2684380046f * ldt2 + 2.6097574011f * mdt2 - 0.3413193965f * sdt2; + + float u_g = g1 / (g1 * g1 - 0.5f * g * g2); + float t_g = -g * u_g; + + b = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s - 1; + float b1 = -0.0041960863f * ldt - 0.7034186147f * mdt + 1.7076147010f * sdt; + float b2 = -0.0041960863f * ldt2 - 0.7034186147f * mdt2 + 1.7076147010f * sdt2; + + float u_b = b1 / (b1 * b1 - 0.5f * b * b2); + float t_b = -b * u_b; + + t_r = u_r >= 0.f ? t_r : FLT_MAX; + t_g = u_g >= 0.f ? t_g : FLT_MAX; + t_b = u_b >= 0.f ? t_b : FLT_MAX; + + t += fmin(t_r, fmin(t_g, t_b)); + } + } + } + + return t; + } + + static float find_gamut_intersection(float a, float b, float L1, float C1, float L0) { + // Find the cusp of the gamut triangle + LC cusp = find_cusp(a, b); + + return find_gamut_intersection(a, b, L1, C1, L0, cusp); + } + + static RGB gamut_clip_preserve_chroma(RGB rgb) { + if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0) + return rgb; + + Lab lab = linear_srgb_to_oklab(rgb); + + float L = lab.L; + float eps = 0.00001f; + float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b)); + float a_ = lab.a / C; + float b_ = lab.b / C; + + float L0 = clamp(L, 0, 1); + + float t = find_gamut_intersection(a_, b_, L, C, L0); + float L_clipped = L0 * (1 - t) + t * L; + float C_clipped = t * C; + + return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ }); + } + + static RGB gamut_clip_project_to_0_5(RGB rgb) { + if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0) + return rgb; + + Lab lab = linear_srgb_to_oklab(rgb); + + float L = lab.L; + float eps = 0.00001f; + float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b)); + float a_ = lab.a / C; + float b_ = lab.b / C; + + float L0 = 0.5; + + float t = find_gamut_intersection(a_, b_, L, C, L0); + float L_clipped = L0 * (1 - t) + t * L; + float C_clipped = t * C; + + return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ }); + } + + static RGB gamut_clip_project_to_L_cusp(RGB rgb) { + if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0) + return rgb; + + Lab lab = linear_srgb_to_oklab(rgb); + + float L = lab.L; + float eps = 0.00001f; + float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b)); + float a_ = lab.a / C; + float b_ = lab.b / C; + + // The cusp is computed here and in find_gamut_intersection, an optimized solution would only compute it once. + LC cusp = find_cusp(a_, b_); + + float L0 = cusp.L; + + float t = find_gamut_intersection(a_, b_, L, C, L0); + + float L_clipped = L0 * (1 - t) + t * L; + float C_clipped = t * C; + + return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ }); + } + + static RGB gamut_clip_adaptive_L0_0_5(RGB rgb, float alpha = 0.05f) { + if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0) + return rgb; + + Lab lab = linear_srgb_to_oklab(rgb); + + float L = lab.L; + float eps = 0.00001f; + float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b)); + float a_ = lab.a / C; + float b_ = lab.b / C; + + float Ld = L - 0.5f; + float e1 = 0.5f + fabs(Ld) + alpha * C; + float L0 = 0.5f * (1.f + sgn(Ld) * (e1 - sqrtf(e1 * e1 - 2.f * fabs(Ld)))); + + float t = find_gamut_intersection(a_, b_, L, C, L0); + float L_clipped = L0 * (1.f - t) + t * L; + float C_clipped = t * C; + + return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ }); + } + + static RGB gamut_clip_adaptive_L0_L_cusp(RGB rgb, float alpha = 0.05f) { + if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0) + return rgb; + + Lab lab = linear_srgb_to_oklab(rgb); + + float L = lab.L; + float eps = 0.00001f; + float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b)); + float a_ = lab.a / C; + float b_ = lab.b / C; + + // The cusp is computed here and in find_gamut_intersection, an optimized solution would only compute it once. + LC cusp = find_cusp(a_, b_); + + float Ld = L - cusp.L; + float k = 2.f * (Ld > 0 ? 1.f - cusp.L : cusp.L); + + float e1 = 0.5f * k + fabs(Ld) + alpha * C / k; + float L0 = cusp.L + 0.5f * (sgn(Ld) * (e1 - sqrtf(e1 * e1 - 2.f * k * fabs(Ld)))); + + float t = find_gamut_intersection(a_, b_, L, C, L0); + float L_clipped = L0 * (1.f - t) + t * L; + float C_clipped = t * C; + + return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ }); + } + + static float toe(float x) { + constexpr float k_1 = 0.206f; + constexpr float k_2 = 0.03f; + constexpr float k_3 = (1.f + k_1) / (1.f + k_2); + return 0.5f * (k_3 * x - k_1 + sqrtf((k_3 * x - k_1) * (k_3 * x - k_1) + 4 * k_2 * k_3 * x)); + } + + static float toe_inv(float x) { + constexpr float k_1 = 0.206f; + constexpr float k_2 = 0.03f; + constexpr float k_3 = (1.f + k_1) / (1.f + k_2); + return (x * x + k_1 * x) / (k_3 * (x + k_2)); + } + + static ST to_ST(LC cusp) { + float L = cusp.L; + float C = cusp.C; + return { C / L, C / (1 - L) }; + } + + // Returns a smooth approximation of the location of the cusp + // This polynomial was created by an optimization process + // It has been designed so that S_mid < S_max and T_mid < T_max + static ST get_ST_mid(float a_, float b_) { + float S = 0.11516993f + 1.f / (+7.44778970f + 4.15901240f * b_ + a_ * (-2.19557347f + 1.75198401f * b_ + a_ * (-2.13704948f - 10.02301043f * b_ + a_ * (-4.24894561f + 5.38770819f * b_ + 4.69891013f * a_)))); + + float T = 0.11239642f + 1.f / (+1.61320320f - 0.68124379f * b_ + a_ * (+0.40370612f + 0.90148123f * b_ + a_ * (-0.27087943f + 0.61223990f * b_ + a_ * (+0.00299215f - 0.45399568f * b_ - 0.14661872f * a_)))); + + return { S, T }; + } + + struct Cs { + float C_0; + float C_mid; + float C_max; + }; + static Cs get_Cs(float L, float a_, float b_) { + LC cusp = find_cusp(a_, b_); + + float C_max = find_gamut_intersection(a_, b_, L, 1, L, cusp); + ST ST_max = to_ST(cusp); + + // Scale factor to compensate for the curved part of gamut shape: + float k = C_max / fmin((L * ST_max.S), (1 - L) * ST_max.T); + + float C_mid; + { + ST ST_mid = get_ST_mid(a_, b_); + + // Use a soft minimum function, instead of a sharp triangle shape to get a smooth value for chroma. + float C_a = L * ST_mid.S; + float C_b = (1.f - L) * ST_mid.T; + C_mid = 0.9f * k * sqrtf(sqrtf(1.f / (1.f / (C_a * C_a * C_a * C_a) + 1.f / (C_b * C_b * C_b * C_b)))); + } + + float C_0; + { + // for C_0, the shape is independent of hue, so ST are constant. Values picked to roughly be the average values of ST. + float C_a = L * 0.4f; + float C_b = (1.f - L) * 0.8f; + + // Use a soft minimum function, instead of a sharp triangle shape to get a smooth value for chroma. + C_0 = sqrtf(1.f / (1.f / (C_a * C_a) + 1.f / (C_b * C_b))); + } + + return { C_0, C_mid, C_max }; + } + + static RGB okhsl_to_srgb(HSL hsl) { + float h = hsl.h; + float s = hsl.s; + float l = hsl.l; + + if (l == 1.0f) { + return { 1.f, 1.f, 1.f }; + } + + else if (l == 0.f) { + return { 0.f, 0.f, 0.f }; + } + + float a_ = cosf(2.f * pi * h); + float b_ = sinf(2.f * pi * h); + float L = toe_inv(l); + + Cs cs = get_Cs(L, a_, b_); + float C_0 = cs.C_0; + float C_mid = cs.C_mid; + float C_max = cs.C_max; + + float mid = 0.8f; + float mid_inv = 1.25f; + + float C, t, k_0, k_1, k_2; + + if (s < mid) { + t = mid_inv * s; + + k_1 = mid * C_0; + k_2 = (1.f - k_1 / C_mid); + + C = t * k_1 / (1.f - k_2 * t); + } else { + t = (s - mid) / (1 - mid); + + k_0 = C_mid; + k_1 = (1.f - mid) * C_mid * C_mid * mid_inv * mid_inv / C_0; + k_2 = (1.f - (k_1) / (C_max - C_mid)); + + C = k_0 + t * k_1 / (1.f - k_2 * t); + } + + RGB rgb = oklab_to_linear_srgb({ L, C * a_, C * b_ }); + return { + srgb_transfer_function(rgb.r), + srgb_transfer_function(rgb.g), + srgb_transfer_function(rgb.b), + }; + } + + static HSL srgb_to_okhsl(RGB rgb) { + Lab lab = linear_srgb_to_oklab({ srgb_transfer_function_inv(rgb.r), + srgb_transfer_function_inv(rgb.g), + srgb_transfer_function_inv(rgb.b) }); + + float C = sqrtf(lab.a * lab.a + lab.b * lab.b); + float a_ = lab.a / C; + float b_ = lab.b / C; + + float L = lab.L; + float h = 0.5f + 0.5f * atan2f(-lab.b, -lab.a) / pi; + + Cs cs = get_Cs(L, a_, b_); + float C_0 = cs.C_0; + float C_mid = cs.C_mid; + float C_max = cs.C_max; + + // Inverse of the interpolation in okhsl_to_srgb: + + float mid = 0.8f; + float mid_inv = 1.25f; + + float s; + if (C < C_mid) { + float k_1 = mid * C_0; + float k_2 = (1.f - k_1 / C_mid); + + float t = C / (k_1 + k_2 * C); + s = t * mid; + } else { + float k_0 = C_mid; + float k_1 = (1.f - mid) * C_mid * C_mid * mid_inv * mid_inv / C_0; + float k_2 = (1.f - (k_1) / (C_max - C_mid)); + + float t = (C - k_0) / (k_1 + k_2 * (C - k_0)); + s = mid + (1.f - mid) * t; + } + + float l = toe(L); + return { h, s, l }; + } + + static RGB okhsv_to_srgb(HSV hsv) { + float h = hsv.h; + float s = hsv.s; + float v = hsv.v; + + float a_ = cosf(2.f * pi * h); + float b_ = sinf(2.f * pi * h); + + LC cusp = find_cusp(a_, b_); + ST ST_max = to_ST(cusp); + float S_max = ST_max.S; + float T_max = ST_max.T; + float S_0 = 0.5f; + float k = 1 - S_0 / S_max; + + // first we compute L and V as if the gamut is a perfect triangle: + + // L, C when v==1: + float L_v = 1 - s * S_0 / (S_0 + T_max - T_max * k * s); + float C_v = s * T_max * S_0 / (S_0 + T_max - T_max * k * s); + + float L = v * L_v; + float C = v * C_v; + + // then we compensate for both toe and the curved top part of the triangle: + float L_vt = toe_inv(L_v); + float C_vt = C_v * L_vt / L_v; + + float L_new = toe_inv(L); + C = C * L_new / L; + L = L_new; + + RGB rgb_scale = oklab_to_linear_srgb({ L_vt, a_ * C_vt, b_ * C_vt }); + float scale_L = cbrtf(1.f / fmax(fmax(rgb_scale.r, rgb_scale.g), fmax(rgb_scale.b, 0.f))); + + L = L * scale_L; + C = C * scale_L; + + RGB rgb = oklab_to_linear_srgb({ L, C * a_, C * b_ }); + return { + srgb_transfer_function(rgb.r), + srgb_transfer_function(rgb.g), + srgb_transfer_function(rgb.b), + }; + } + + static HSV srgb_to_okhsv(RGB rgb) { + Lab lab = linear_srgb_to_oklab({ srgb_transfer_function_inv(rgb.r), + srgb_transfer_function_inv(rgb.g), + srgb_transfer_function_inv(rgb.b) }); + + float C = sqrtf(lab.a * lab.a + lab.b * lab.b); + float a_ = lab.a / C; + float b_ = lab.b / C; + + float L = lab.L; + float h = 0.5f + 0.5f * atan2f(-lab.b, -lab.a) / pi; + + LC cusp = find_cusp(a_, b_); + ST ST_max = to_ST(cusp); + float S_max = ST_max.S; + float T_max = ST_max.T; + float S_0 = 0.5f; + float k = 1 - S_0 / S_max; + + // first we find L_v, C_v, L_vt and C_vt + + float t = T_max / (C + L * T_max); + float L_v = t * L; + float C_v = t * C; + + float L_vt = toe_inv(L_v); + float C_vt = C_v * L_vt / L_v; + + // we can then use these to invert the step that compensates for the toe and the curved top part of the triangle: + RGB rgb_scale = oklab_to_linear_srgb({ L_vt, a_ * C_vt, b_ * C_vt }); + float scale_L = cbrtf(1.f / fmax(fmax(rgb_scale.r, rgb_scale.g), fmax(rgb_scale.b, 0.f))); + + L = L / scale_L; + C = C / scale_L; + + C = C * toe(L) / L; + L = toe(L); + + // we can now compute v and s: + + float v = L / L_v; + float s = (S_0 + T_max) * C_v / ((T_max * S_0) + T_max * k * C_v); + + return { h, s, v }; + } + }; + +} // namespace godot + +#endif // GODOT_OK_COLOR_HPP diff --git a/include/godot_cpp/variant/plane.hpp b/include/godot_cpp/variant/plane.hpp index 829f801f4..9b6d6d1e1 100644 --- a/include/godot_cpp/variant/plane.hpp +++ b/include/godot_cpp/variant/plane.hpp @@ -50,7 +50,7 @@ struct _NO_DISCARD_ Plane { /* Plane-Point operations */ - _FORCE_INLINE_ Vector3 center() const { return normal * d; } + _FORCE_INLINE_ Vector3 get_center() const { return normal * d; } Vector3 get_any_perpendicular_normal() const; _FORCE_INLINE_ bool is_point_over(const Vector3 &p_point) const; ///< Point is over plane diff --git a/include/godot_cpp/variant/projection.hpp b/include/godot_cpp/variant/projection.hpp index 1de6c0244..92f0daf6a 100644 --- a/include/godot_cpp/variant/projection.hpp +++ b/include/godot_cpp/variant/projection.hpp @@ -66,11 +66,11 @@ struct _NO_DISCARD_ Projection { return columns[p_axis]; } - float determinant() const; + real_t determinant() const; void set_identity(); void set_zero(); void set_light_bias(); - void set_depth_correction(bool p_flip_y = true); + void set_depth_correction(bool p_flip_y = true, bool p_reverse_z = true, bool p_remap_z = true); void set_light_atlas_rect(const Rect2 &p_rect); void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false); @@ -149,7 +149,7 @@ struct _NO_DISCARD_ Projection { return !(*this == p_cam); } - float get_lod_multiplier() const; + real_t get_lod_multiplier() const; Projection(); Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w); diff --git a/include/godot_cpp/variant/quaternion.hpp b/include/godot_cpp/variant/quaternion.hpp index 5de91b207..df1e34f2b 100644 --- a/include/godot_cpp/variant/quaternion.hpp +++ b/include/godot_cpp/variant/quaternion.hpp @@ -31,6 +31,7 @@ #ifndef GODOT_QUATERNION_HPP #define GODOT_QUATERNION_HPP +#include #include #include @@ -47,11 +48,11 @@ struct _NO_DISCARD_ Quaternion { real_t components[4] = { 0, 0, 0, 1.0 }; }; - _FORCE_INLINE_ real_t &operator[](int idx) { - return components[idx]; + _FORCE_INLINE_ real_t &operator[](int p_idx) { + return components[p_idx]; } - _FORCE_INLINE_ const real_t &operator[](int idx) const { - return components[idx]; + _FORCE_INLINE_ const real_t &operator[](int p_idx) const { + return components[p_idx]; } _FORCE_INLINE_ real_t length_squared() const; bool is_equal_approx(const Quaternion &p_quaternion) const; @@ -66,9 +67,8 @@ struct _NO_DISCARD_ Quaternion { _FORCE_INLINE_ real_t dot(const Quaternion &p_q) const; real_t angle_to(const Quaternion &p_to) const; - Vector3 get_euler_xyz() const; - Vector3 get_euler_yxz() const; - Vector3 get_euler() const { return get_euler_yxz(); } + Vector3 get_euler(EulerOrder p_order = EULER_ORDER_YXZ) const; + static Quaternion from_euler(const Vector3 &p_euler); Quaternion slerp(const Quaternion &p_to, const real_t &p_weight) const; Quaternion slerpni(const Quaternion &p_to, const real_t &p_weight) const; @@ -89,28 +89,28 @@ struct _NO_DISCARD_ Quaternion { void operator*=(const Quaternion &p_q); Quaternion operator*(const Quaternion &p_q) const; - _FORCE_INLINE_ Vector3 xform(const Vector3 &v) const { + _FORCE_INLINE_ Vector3 xform(const Vector3 &p_v) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), v, "The quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), p_v, "The quaternion " + operator String() + " must be normalized."); #endif Vector3 u(x, y, z); - Vector3 uv = u.cross(v); - return v + ((uv * w) + u.cross(uv)) * ((real_t)2); + Vector3 uv = u.cross(p_v); + return p_v + ((uv * w) + u.cross(uv)) * ((real_t)2); } - _FORCE_INLINE_ Vector3 xform_inv(const Vector3 &v) const { - return inverse().xform(v); + _FORCE_INLINE_ Vector3 xform_inv(const Vector3 &p_v) const { + return inverse().xform(p_v); } _FORCE_INLINE_ void operator+=(const Quaternion &p_q); _FORCE_INLINE_ void operator-=(const Quaternion &p_q); - _FORCE_INLINE_ void operator*=(const real_t &s); - _FORCE_INLINE_ void operator/=(const real_t &s); - _FORCE_INLINE_ Quaternion operator+(const Quaternion &q2) const; - _FORCE_INLINE_ Quaternion operator-(const Quaternion &q2) const; + _FORCE_INLINE_ void operator*=(const real_t &p_s); + _FORCE_INLINE_ void operator/=(const real_t &p_s); + _FORCE_INLINE_ Quaternion operator+(const Quaternion &p_q2) const; + _FORCE_INLINE_ Quaternion operator-(const Quaternion &p_q2) const; _FORCE_INLINE_ Quaternion operator-() const; - _FORCE_INLINE_ Quaternion operator*(const real_t &s) const; - _FORCE_INLINE_ Quaternion operator/(const real_t &s) const; + _FORCE_INLINE_ Quaternion operator*(const real_t &p_s) const; + _FORCE_INLINE_ Quaternion operator/(const real_t &p_s) const; _FORCE_INLINE_ bool operator==(const Quaternion &p_quaternion) const; _FORCE_INLINE_ bool operator!=(const Quaternion &p_quaternion) const; @@ -128,8 +128,6 @@ struct _NO_DISCARD_ Quaternion { Quaternion(const Vector3 &p_axis, real_t p_angle); - Quaternion(const Vector3 &p_euler); - Quaternion(const Quaternion &p_q) : x(p_q.x), y(p_q.y), @@ -144,9 +142,9 @@ struct _NO_DISCARD_ Quaternion { w = p_q.w; } - Quaternion(const Vector3 &v0, const Vector3 &v1) { // Shortest arc. - Vector3 c = v0.cross(v1); - real_t d = v0.dot(v1); + Quaternion(const Vector3 &p_v0, const Vector3 &p_v1) { // Shortest arc. + Vector3 c = p_v0.cross(p_v1); + real_t d = p_v0.dot(p_v1); if (d < -1.0f + (real_t)CMP_EPSILON) { x = 0; @@ -187,25 +185,25 @@ void Quaternion::operator-=(const Quaternion &p_q) { w -= p_q.w; } -void Quaternion::operator*=(const real_t &s) { - x *= s; - y *= s; - z *= s; - w *= s; +void Quaternion::operator*=(const real_t &p_s) { + x *= p_s; + y *= p_s; + z *= p_s; + w *= p_s; } -void Quaternion::operator/=(const real_t &s) { - *this *= 1.0f / s; +void Quaternion::operator/=(const real_t &p_s) { + *this *= 1.0f / p_s; } -Quaternion Quaternion::operator+(const Quaternion &q2) const { +Quaternion Quaternion::operator+(const Quaternion &p_q2) const { const Quaternion &q1 = *this; - return Quaternion(q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w); + return Quaternion(q1.x + p_q2.x, q1.y + p_q2.y, q1.z + p_q2.z, q1.w + p_q2.w); } -Quaternion Quaternion::operator-(const Quaternion &q2) const { +Quaternion Quaternion::operator-(const Quaternion &p_q2) const { const Quaternion &q1 = *this; - return Quaternion(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w); + return Quaternion(q1.x - p_q2.x, q1.y - p_q2.y, q1.z - p_q2.z, q1.w - p_q2.w); } Quaternion Quaternion::operator-() const { @@ -213,12 +211,12 @@ Quaternion Quaternion::operator-() const { return Quaternion(-q2.x, -q2.y, -q2.z, -q2.w); } -Quaternion Quaternion::operator*(const real_t &s) const { - return Quaternion(x * s, y * s, z * s, w * s); +Quaternion Quaternion::operator*(const real_t &p_s) const { + return Quaternion(x * p_s, y * p_s, z * p_s, w * p_s); } -Quaternion Quaternion::operator/(const real_t &s) const { - return *this * (1.0f / s); +Quaternion Quaternion::operator/(const real_t &p_s) const { + return *this * (1.0f / p_s); } bool Quaternion::operator==(const Quaternion &p_quaternion) const { diff --git a/include/godot_cpp/variant/rect2.hpp b/include/godot_cpp/variant/rect2.hpp index 31c81aa27..6bf0d4b7d 100644 --- a/include/godot_cpp/variant/rect2.hpp +++ b/include/godot_cpp/variant/rect2.hpp @@ -146,7 +146,7 @@ struct _NO_DISCARD_ Rect2 { return size.x > 0.0f && size.y > 0.0f; } - // Returns the intersection between two Rect2s or an empty Rect2 if there is no intersection + // Returns the intersection 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; @@ -283,6 +283,10 @@ struct _NO_DISCARD_ Rect2 { return Rect2(position + size.minf(0), size.abs()); } + _FORCE_INLINE_ Rect2 round() const { + return Rect2(position.round(), size.round()); + } + Vector2 get_support(const Vector2 &p_normal) const { Vector2 half_extents = size * 0.5f; Vector2 ofs = position + half_extents; @@ -305,14 +309,14 @@ struct _NO_DISCARD_ Rect2 { i_f = i; Vector2 r = (b - a); - float l = r.length(); + const real_t l = r.length(); if (l == 0.0f) { continue; } // Check inside. Vector2 tg = r.orthogonal(); - float s = tg.dot(center) - tg.dot(a); + const real_t s = tg.dot(center) - tg.dot(a); if (s < 0.0f) { side_plus++; } else { @@ -328,8 +332,8 @@ struct _NO_DISCARD_ Rect2 { Vector2 t13 = (position - a) * ir; Vector2 t24 = (end - a) * ir; - float tmin = Math::max(Math::min(t13.x, t24.x), Math::min(t13.y, t24.y)); - float tmax = Math::min(Math::max(t13.x, t24.x), Math::max(t13.y, t24.y)); + const real_t tmin = Math::max(Math::min(t13.x, t24.x), Math::min(t13.y, t24.y)); + const real_t tmax = Math::min(Math::max(t13.x, t24.x), Math::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) { diff --git a/include/godot_cpp/variant/rect2i.hpp b/include/godot_cpp/variant/rect2i.hpp index 57b090592..29a522ba3 100644 --- a/include/godot_cpp/variant/rect2i.hpp +++ b/include/godot_cpp/variant/rect2i.hpp @@ -89,7 +89,7 @@ struct _NO_DISCARD_ Rect2i { return size.x > 0 && size.y > 0; } - // Returns the intersection between two Rect2is or an empty Rect2i if there is no intersection + // Returns the intersection 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; diff --git a/include/godot_cpp/variant/transform2d.hpp b/include/godot_cpp/variant/transform2d.hpp index d73323f31..7dd3f4457 100644 --- a/include/godot_cpp/variant/transform2d.hpp +++ b/include/godot_cpp/variant/transform2d.hpp @@ -53,8 +53,8 @@ struct _NO_DISCARD_ Transform2D { Vector2 columns[3]; - _FORCE_INLINE_ real_t tdotx(const Vector2 &v) const { return columns[0][0] * v.x + columns[1][0] * v.y; } - _FORCE_INLINE_ real_t tdoty(const Vector2 &v) const { return columns[0][1] * v.x + columns[1][1] * v.y; } + _FORCE_INLINE_ real_t tdotx(const Vector2 &p_v) const { return columns[0][0] * p_v.x + columns[1][0] * p_v.y; } + _FORCE_INLINE_ real_t tdoty(const Vector2 &p_v) const { return columns[0][1] * p_v.x + columns[1][1] * p_v.y; } const Vector2 &operator[](int p_idx) const { return columns[p_idx]; } Vector2 &operator[](int p_idx) { return columns[p_idx]; } @@ -78,7 +78,7 @@ struct _NO_DISCARD_ Transform2D { void translate_local(const real_t p_tx, const real_t p_ty); void translate_local(const Vector2 &p_translation); - real_t basis_determinant() const; + real_t determinant() const; Size2 get_scale() const; void set_scale(const Size2 &p_scale); @@ -86,7 +86,6 @@ struct _NO_DISCARD_ Transform2D { _FORCE_INLINE_ const Vector2 &get_origin() const { return columns[2]; } _FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { columns[2] = p_origin; } - Transform2D basis_scaled(const Size2 &p_scale) const; Transform2D scaled(const Size2 &p_scale) const; Transform2D scaled_local(const Size2 &p_scale) const; Transform2D translated(const Vector2 &p_offset) const; @@ -98,6 +97,7 @@ struct _NO_DISCARD_ Transform2D { void orthonormalize(); Transform2D orthonormalized() const; + bool is_conformal() const; bool is_equal_approx(const Transform2D &p_transform) const; bool is_finite() const; @@ -110,6 +110,8 @@ struct _NO_DISCARD_ Transform2D { Transform2D operator*(const Transform2D &p_transform) const; void operator*=(const real_t p_val); Transform2D operator*(const real_t p_val) const; + void operator/=(const real_t p_val); + Transform2D operator/(const real_t p_val) const; Transform2D interpolate_with(const Transform2D &p_transform, const real_t p_c) const; @@ -124,13 +126,13 @@ struct _NO_DISCARD_ Transform2D { operator String() const; - Transform2D(const real_t xx, const real_t xy, const real_t yx, const real_t yy, const real_t ox, const real_t oy) { - columns[0][0] = xx; - columns[0][1] = xy; - columns[1][0] = yx; - columns[1][1] = yy; - columns[2][0] = ox; - columns[2][1] = oy; + Transform2D(const real_t p_xx, const real_t p_xy, const real_t p_yx, const real_t p_yy, const real_t p_ox, const real_t p_oy) { + columns[0][0] = p_xx; + columns[0][1] = p_xy; + columns[1][0] = p_yx; + columns[1][1] = p_yy; + columns[2][0] = p_ox; + columns[2][1] = p_oy; } Transform2D(const Vector2 &p_x, const Vector2 &p_y, const Vector2 &p_origin) { diff --git a/include/godot_cpp/variant/transform3d.hpp b/include/godot_cpp/variant/transform3d.hpp index 6fa5999ed..349f4df97 100644 --- a/include/godot_cpp/variant/transform3d.hpp +++ b/include/godot_cpp/variant/transform3d.hpp @@ -55,8 +55,8 @@ struct _NO_DISCARD_ Transform3D { void rotate(const Vector3 &p_axis, real_t p_angle); void rotate_basis(const Vector3 &p_axis, real_t p_angle); - void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)); - Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)) const; + void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false); + Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false) const; void scale(const Vector3 &p_scale); Transform3D scaled(const Vector3 &p_scale) const; @@ -107,6 +107,8 @@ struct _NO_DISCARD_ Transform3D { Transform3D operator*(const Transform3D &p_transform) const; void operator*=(const real_t p_val); Transform3D operator*(const real_t p_val) const; + void operator/=(const real_t p_val); + Transform3D operator/(const real_t p_val) const; Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const; @@ -116,11 +118,11 @@ struct _NO_DISCARD_ Transform3D { basis.xform(v)); } - void set(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 tx, real_t ty, real_t tz) { - basis.set(xx, xy, xz, yx, yy, yz, zx, zy, zz); - origin.x = tx; - origin.y = ty; - origin.z = tz; + void set(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_tx, real_t p_ty, real_t p_tz) { + basis.set(p_xx, p_xy, p_xz, p_yx, p_yy, p_yz, p_zx, p_zy, p_zz); + origin.x = p_tx; + origin.y = p_ty; + origin.z = p_tz; } operator String() const; @@ -128,7 +130,7 @@ struct _NO_DISCARD_ Transform3D { Transform3D() {} Transform3D(const Basis &p_basis, const Vector3 &p_origin = Vector3()); Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin); - Transform3D(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); + Transform3D(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_ox, real_t p_oy, real_t p_oz); }; _FORCE_INLINE_ Vector3 Transform3D::xform(const Vector3 &p_vector) const { diff --git a/include/godot_cpp/variant/vector2.hpp b/include/godot_cpp/variant/vector2.hpp index 8f08985f3..ddd3ba213 100644 --- a/include/godot_cpp/variant/vector2.hpp +++ b/include/godot_cpp/variant/vector2.hpp @@ -62,13 +62,13 @@ struct _NO_DISCARD_ Vector2 { real_t coord[2] = { 0 }; }; - _FORCE_INLINE_ real_t &operator[](int p_idx) { - DEV_ASSERT((unsigned int)p_idx < 2); - return coord[p_idx]; + _FORCE_INLINE_ real_t &operator[](int p_axis) { + DEV_ASSERT((unsigned int)p_axis < 2); + return coord[p_axis]; } - _FORCE_INLINE_ const real_t &operator[](int p_idx) const { - DEV_ASSERT((unsigned int)p_idx < 2); - return coord[p_idx]; + _FORCE_INLINE_ const real_t &operator[](int p_axis) const { + DEV_ASSERT((unsigned int)p_axis < 2); + return coord[p_axis]; } _FORCE_INLINE_ Vector2::Axis min_axis_index() const { @@ -122,6 +122,7 @@ struct _NO_DISCARD_ Vector2 { _FORCE_INLINE_ Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight) const; _FORCE_INLINE_ Vector2 cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const; _FORCE_INLINE_ Vector2 bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const; + _FORCE_INLINE_ Vector2 bezier_derivative(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const; Vector2 move_toward(const Vector2 &p_to, const real_t p_delta) const; @@ -139,16 +140,16 @@ struct _NO_DISCARD_ Vector2 { void operator-=(const Vector2 &p_v); Vector2 operator*(const Vector2 &p_v1) const; - Vector2 operator*(const real_t &rvalue) const; - void operator*=(const real_t &rvalue); - void operator*=(const Vector2 &rvalue) { *this = *this * rvalue; } + Vector2 operator*(const real_t &p_rvalue) const; + void operator*=(const real_t &p_rvalue); + void operator*=(const Vector2 &p_rvalue) { *this = *this * p_rvalue; } Vector2 operator/(const Vector2 &p_v1) const; - Vector2 operator/(const real_t &rvalue) const; + Vector2 operator/(const real_t &p_rvalue) const; - void operator/=(const real_t &rvalue); - void operator/=(const Vector2 &rvalue) { *this = *this / rvalue; } + void operator/=(const real_t &p_rvalue); + void operator/=(const Vector2 &p_rvalue) { *this = *this / p_rvalue; } Vector2 operator-() const; @@ -218,26 +219,26 @@ _FORCE_INLINE_ Vector2 Vector2::operator*(const Vector2 &p_v1) const { return Vector2(x * p_v1.x, y * p_v1.y); } -_FORCE_INLINE_ Vector2 Vector2::operator*(const real_t &rvalue) const { - return Vector2(x * rvalue, y * rvalue); +_FORCE_INLINE_ Vector2 Vector2::operator*(const real_t &p_rvalue) const { + return Vector2(x * p_rvalue, y * p_rvalue); } -_FORCE_INLINE_ void Vector2::operator*=(const real_t &rvalue) { - x *= rvalue; - y *= rvalue; +_FORCE_INLINE_ void Vector2::operator*=(const real_t &p_rvalue) { + x *= p_rvalue; + y *= p_rvalue; } _FORCE_INLINE_ Vector2 Vector2::operator/(const Vector2 &p_v1) const { return Vector2(x / p_v1.x, y / p_v1.y); } -_FORCE_INLINE_ Vector2 Vector2::operator/(const real_t &rvalue) const { - return Vector2(x / rvalue, y / rvalue); +_FORCE_INLINE_ Vector2 Vector2::operator/(const real_t &p_rvalue) const { + return Vector2(x / p_rvalue, y / p_rvalue); } -_FORCE_INLINE_ void Vector2::operator/=(const real_t &rvalue) { - x /= rvalue; - y /= rvalue; +_FORCE_INLINE_ void Vector2::operator/=(const real_t &p_rvalue) { + x /= p_rvalue; + y /= p_rvalue; } _FORCE_INLINE_ Vector2 Vector2::operator-() const { @@ -254,10 +255,8 @@ _FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const { Vector2 Vector2::lerp(const Vector2 &p_to, const real_t p_weight) const { Vector2 res = *this; - - res.x += (p_weight * (p_to.x - x)); - res.y += (p_weight * (p_to.y - y)); - + res.x = Math::lerp(res.x, p_to.x, p_weight); + res.y = Math::lerp(res.y, p_to.y, p_weight); return res; } @@ -290,15 +289,16 @@ Vector2 Vector2::cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_ Vector2 Vector2::bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const { Vector2 res = *this; + res.x = Math::bezier_interpolate(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); + res.y = Math::bezier_interpolate(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); + return res; +} - /* Formula from Wikipedia article on Bezier curves. */ - real_t omt = (1.0 - p_t); - real_t omt2 = omt * omt; - real_t omt3 = omt2 * omt; - real_t t2 = p_t * p_t; - real_t t3 = t2 * p_t; - - return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3; +Vector2 Vector2::bezier_derivative(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const { + Vector2 res = *this; + res.x = Math::bezier_derivative(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); + res.y = Math::bezier_derivative(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); + return res; } Vector2 Vector2::direction_to(const Vector2 &p_to) const { diff --git a/include/godot_cpp/variant/vector2i.hpp b/include/godot_cpp/variant/vector2i.hpp index 0d787c3fc..69b8c8d6d 100644 --- a/include/godot_cpp/variant/vector2i.hpp +++ b/include/godot_cpp/variant/vector2i.hpp @@ -62,13 +62,13 @@ struct _NO_DISCARD_ Vector2i { int32_t coord[2] = { 0 }; }; - _FORCE_INLINE_ int32_t &operator[](int p_idx) { - DEV_ASSERT((unsigned int)p_idx < 2); - return coord[p_idx]; + _FORCE_INLINE_ int32_t &operator[](int p_axis) { + DEV_ASSERT((unsigned int)p_axis < 2); + return coord[p_axis]; } - _FORCE_INLINE_ const int32_t &operator[](int p_idx) const { - DEV_ASSERT((unsigned int)p_idx < 2); - return coord[p_idx]; + _FORCE_INLINE_ const int32_t &operator[](int p_axis) const { + DEV_ASSERT((unsigned int)p_axis < 2); + return coord[p_axis]; } _FORCE_INLINE_ Vector2i::Axis min_axis_index() const { @@ -95,22 +95,30 @@ struct _NO_DISCARD_ Vector2i { return Vector2i(MAX(x, p_scalar), MAX(y, p_scalar)); } + double distance_to(const Vector2i &p_to) const { + return (p_to - *this).length(); + } + + int64_t distance_squared_to(const Vector2i &p_to) const { + return (p_to - *this).length_squared(); + } + Vector2i operator+(const Vector2i &p_v) const; void operator+=(const Vector2i &p_v); Vector2i operator-(const Vector2i &p_v) const; void operator-=(const Vector2i &p_v); Vector2i operator*(const Vector2i &p_v1) const; - Vector2i operator*(const int32_t &rvalue) const; - void operator*=(const int32_t &rvalue); + Vector2i operator*(const int32_t &p_rvalue) const; + void operator*=(const int32_t &p_rvalue); Vector2i operator/(const Vector2i &p_v1) const; - Vector2i operator/(const int32_t &rvalue) const; - void operator/=(const int32_t &rvalue); + Vector2i operator/(const int32_t &p_rvalue) const; + void operator/=(const int32_t &p_rvalue); Vector2i operator%(const Vector2i &p_v1) const; - Vector2i operator%(const int32_t &rvalue) const; - void operator%=(const int32_t &rvalue); + Vector2i operator%(const int32_t &p_rvalue) const; + void operator%=(const int32_t &p_rvalue); Vector2i operator-() const; bool operator<(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); } @@ -125,16 +133,13 @@ struct _NO_DISCARD_ Vector2i { int64_t length_squared() const; double length() const; - int64_t distance_squared_to(const Vector2i &p_to) const; - double distance_to(const Vector2i &p_to) const; - real_t aspect() const { return width / (real_t)height; } - Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); } + Vector2i sign() const { return Vector2i(Math::sign(x), Math::sign(y)); } Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); } - Vector2i snapped(const Vector2i &p_step) const; - Vector2i snappedi(int32_t p_step) const; Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const; Vector2i clampi(int32_t p_min, int32_t p_max) const; + Vector2i snapped(const Vector2i &p_step) const; + Vector2i snappedi(int32_t p_step) const; operator String() const; operator Vector2() const; diff --git a/include/godot_cpp/variant/vector3.hpp b/include/godot_cpp/variant/vector3.hpp index f256c3895..5ff20a76a 100644 --- a/include/godot_cpp/variant/vector3.hpp +++ b/include/godot_cpp/variant/vector3.hpp @@ -36,7 +36,6 @@ namespace godot { -class String; struct Basis; struct Vector2; struct Vector3i; @@ -105,10 +104,10 @@ struct _NO_DISCARD_ Vector3 { _FORCE_INLINE_ void zero(); - void snap(const Vector3 p_val); - void snapf(real_t p_val); - Vector3 snapped(const Vector3 p_val) const; - Vector3 snappedf(real_t p_val) const; + void snap(const Vector3 &p_step); + void snapf(const real_t &p_step); + Vector3 snapped(const Vector3 &p_step) const; + Vector3 snappedf(const real_t &p_step) const; void rotate(const Vector3 &p_axis, const real_t p_angle); Vector3 rotated(const Vector3 &p_axis, const real_t p_angle) const; @@ -120,13 +119,14 @@ struct _NO_DISCARD_ Vector3 { _FORCE_INLINE_ Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const; _FORCE_INLINE_ Vector3 cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const; _FORCE_INLINE_ Vector3 bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const; + _FORCE_INLINE_ Vector3 bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const; Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const; Vector2 octahedron_encode() const; static Vector3 octahedron_decode(const Vector2 &p_oct); - Vector2 octahedron_tangent_encode(const float sign) const; - static Vector3 octahedron_tangent_decode(const Vector2 &p_oct, float *sign); + Vector2 octahedron_tangent_encode(const float p_sign) const; + static Vector3 octahedron_tangent_decode(const Vector2 &p_oct, float *r_sign); _FORCE_INLINE_ Vector3 cross(const Vector3 &p_with) const; _FORCE_INLINE_ real_t dot(const Vector3 &p_with) const; @@ -213,7 +213,7 @@ Vector3 Vector3::abs() const { } Vector3 Vector3::sign() const { - return Vector3(SIGN(x), SIGN(y), SIGN(z)); + return Vector3(Math::sign(x), Math::sign(y), Math::sign(z)); } Vector3 Vector3::floor() const { @@ -229,10 +229,11 @@ Vector3 Vector3::round() const { } Vector3 Vector3::lerp(const Vector3 &p_to, const real_t p_weight) const { - return Vector3( - x + (p_weight * (p_to.x - x)), - y + (p_weight * (p_to.y - y)), - z + (p_weight * (p_to.z - z))); + Vector3 res = *this; + res.x = Math::lerp(res.x, p_to.x, p_weight); + res.y = Math::lerp(res.y, p_to.y, p_weight); + res.z = Math::lerp(res.z, p_to.z, p_weight); + return res; } Vector3 Vector3::slerp(const Vector3 &p_to, const real_t p_weight) const { @@ -275,15 +276,18 @@ Vector3 Vector3::cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_ Vector3 Vector3::bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const { Vector3 res = *this; + res.x = Math::bezier_interpolate(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); + res.y = Math::bezier_interpolate(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); + res.z = Math::bezier_interpolate(res.z, p_control_1.z, p_control_2.z, p_end.z, p_t); + return res; +} - /* Formula from Wikipedia article on Bezier curves. */ - real_t omt = (1.0 - p_t); - real_t omt2 = omt * omt; - real_t omt3 = omt2 * omt; - real_t t2 = p_t * p_t; - real_t t3 = t2 * p_t; - - return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3; +Vector3 Vector3::bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, real_t p_t) const { + Vector3 res = *this; + res.x = Math::bezier_derivative(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t); + res.y = Math::bezier_derivative(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t); + res.z = Math::bezier_derivative(res.z, p_control_1.z, p_control_2.z, p_end.z, p_t); + return res; } real_t Vector3::distance_to(const Vector3 &p_to) const { @@ -520,9 +524,9 @@ void Vector3::zero() { // slide returns the component of the vector along the given plane, specified by its normal vector. Vector3 Vector3::slide(const Vector3 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized."); + ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 " + p_normal.operator String() + " must be normalized."); #endif - return *this - p_normal * this->dot(p_normal); + return *this - p_normal * dot(p_normal); } Vector3 Vector3::bounce(const Vector3 &p_normal) const { @@ -531,9 +535,9 @@ Vector3 Vector3::bounce(const Vector3 &p_normal) const { Vector3 Vector3::reflect(const Vector3 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized."); + ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 " + p_normal.operator String() + " must be normalized."); #endif - return 2.0f * p_normal * this->dot(p_normal) - *this; + return 2.0f * p_normal * dot(p_normal) - *this; } } // namespace godot diff --git a/include/godot_cpp/variant/vector3i.hpp b/include/godot_cpp/variant/vector3i.hpp index b2cdbbdfd..7eafec537 100644 --- a/include/godot_cpp/variant/vector3i.hpp +++ b/include/godot_cpp/variant/vector3i.hpp @@ -90,17 +90,17 @@ struct _NO_DISCARD_ Vector3i { _FORCE_INLINE_ int64_t length_squared() const; _FORCE_INLINE_ double length() const; - _FORCE_INLINE_ int64_t distance_squared_to(const Vector3i &p_to) const; - _FORCE_INLINE_ double distance_to(const Vector3i &p_to) const; - _FORCE_INLINE_ void zero(); _FORCE_INLINE_ Vector3i abs() const; _FORCE_INLINE_ Vector3i sign() const; - Vector3i snapped(const Vector3i &p_step) const; - Vector3i snappedi(int32_t p_step) const; Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const; Vector3i clampi(int32_t p_min, int32_t p_max) const; + Vector3i snapped(const Vector3i &p_step) const; + Vector3i snappedi(const int32_t &p_step) const; + + _FORCE_INLINE_ double distance_to(const Vector3i &p_to) const; + _FORCE_INLINE_ int64_t distance_squared_to(const Vector3i &p_to) const; /* Operators */ @@ -115,12 +115,12 @@ struct _NO_DISCARD_ Vector3i { _FORCE_INLINE_ Vector3i &operator%=(const Vector3i &p_v); _FORCE_INLINE_ Vector3i operator%(const Vector3i &p_v) const; - _FORCE_INLINE_ Vector3i &operator*=(const int32_t p_scalar); - _FORCE_INLINE_ Vector3i operator*(const int32_t p_scalar) const; - _FORCE_INLINE_ Vector3i &operator/=(const int32_t p_scalar); - _FORCE_INLINE_ Vector3i operator/(const int32_t p_scalar) const; - _FORCE_INLINE_ Vector3i &operator%=(const int32_t p_scalar); - _FORCE_INLINE_ Vector3i operator%(const 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%=(int32_t p_scalar); + _FORCE_INLINE_ Vector3i operator%(int32_t p_scalar) const; _FORCE_INLINE_ Vector3i operator-() const; @@ -135,7 +135,7 @@ struct _NO_DISCARD_ Vector3i { operator Vector3() const; _FORCE_INLINE_ Vector3i() {} - _FORCE_INLINE_ Vector3i(const int32_t p_x, const int32_t p_y, const int32_t p_z) { + _FORCE_INLINE_ Vector3i(int32_t p_x, int32_t p_y, int32_t p_z) { x = p_x; y = p_y; z = p_z; @@ -150,20 +150,20 @@ double Vector3i::length() const { return Math::sqrt((double)length_squared()); } -int64_t Vector3i::distance_squared_to(const Vector3i &p_to) const { - return (p_to - *this).length_squared(); +Vector3i Vector3i::abs() const { + return Vector3i(Math::abs(x), Math::abs(y), Math::abs(z)); } -double Vector3i::distance_to(const Vector3i &p_to) const { - return (p_to - *this).length(); +Vector3i Vector3i::sign() const { + return Vector3i(Math::sign(x), Math::sign(y), Math::sign(z)); } -Vector3i Vector3i::abs() const { - return Vector3i(Math::abs(x), Math::abs(y), Math::abs(z)); +double Vector3i::distance_to(const Vector3i &p_to) const { + return (p_to - *this).length(); } -Vector3i Vector3i::sign() const { - return Vector3i(SIGN(x), SIGN(y), SIGN(z)); +int64_t Vector3i::distance_squared_to(const Vector3i &p_to) const { + return (p_to - *this).length_squared(); } /* Operators */ @@ -223,54 +223,54 @@ 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 int32_t p_scalar) { +Vector3i &Vector3i::operator*=(int32_t p_scalar) { x *= p_scalar; y *= p_scalar; z *= p_scalar; return *this; } -Vector3i Vector3i::operator*(const int32_t p_scalar) const { +Vector3i Vector3i::operator*(int32_t p_scalar) const { return Vector3i(x * p_scalar, y * p_scalar, z * p_scalar); } // Multiplication operators required to workaround issues with LLVM using implicit conversion. -_FORCE_INLINE_ Vector3i operator*(const int32_t p_scalar, const Vector3i &p_vector) { +_FORCE_INLINE_ Vector3i operator*(int32_t p_scalar, const Vector3i &p_vector) { return p_vector * p_scalar; } -_FORCE_INLINE_ Vector3i operator*(const int64_t p_scalar, const Vector3i &p_vector) { +_FORCE_INLINE_ Vector3i operator*(int64_t p_scalar, const Vector3i &p_vector) { return p_vector * p_scalar; } -_FORCE_INLINE_ Vector3i operator*(const float p_scalar, const Vector3i &p_vector) { +_FORCE_INLINE_ Vector3i operator*(float p_scalar, const Vector3i &p_vector) { return p_vector * p_scalar; } -_FORCE_INLINE_ Vector3i operator*(const double p_scalar, const Vector3i &p_vector) { +_FORCE_INLINE_ Vector3i operator*(double p_scalar, const Vector3i &p_vector) { return p_vector * p_scalar; } -Vector3i &Vector3i::operator/=(const int32_t p_scalar) { +Vector3i &Vector3i::operator/=(int32_t p_scalar) { x /= p_scalar; y /= p_scalar; z /= p_scalar; return *this; } -Vector3i Vector3i::operator/(const int32_t p_scalar) const { +Vector3i Vector3i::operator/(int32_t p_scalar) const { return Vector3i(x / p_scalar, y / p_scalar, z / p_scalar); } -Vector3i &Vector3i::operator%=(const int32_t p_scalar) { +Vector3i &Vector3i::operator%=(int32_t p_scalar) { x %= p_scalar; y %= p_scalar; z %= p_scalar; return *this; } -Vector3i Vector3i::operator%(const int32_t p_scalar) const { +Vector3i Vector3i::operator%(int32_t p_scalar) const { return Vector3i(x % p_scalar, y % p_scalar, z % p_scalar); } diff --git a/include/godot_cpp/variant/vector4.hpp b/include/godot_cpp/variant/vector4.hpp index 866e522ba..99db6db26 100644 --- a/include/godot_cpp/variant/vector4.hpp +++ b/include/godot_cpp/variant/vector4.hpp @@ -37,6 +37,7 @@ namespace godot { class String; +struct Vector4i; struct _NO_DISCARD_ Vector4 { static const int AXIS_COUNT = 4; @@ -124,15 +125,15 @@ struct _NO_DISCARD_ Vector4 { _FORCE_INLINE_ void operator-=(const Vector4 &p_vec4); _FORCE_INLINE_ void operator*=(const Vector4 &p_vec4); _FORCE_INLINE_ void operator/=(const Vector4 &p_vec4); - _FORCE_INLINE_ void operator*=(const real_t &s); - _FORCE_INLINE_ void operator/=(const real_t &s); + _FORCE_INLINE_ void operator*=(const real_t &p_s); + _FORCE_INLINE_ void operator/=(const real_t &p_s); _FORCE_INLINE_ Vector4 operator+(const Vector4 &p_vec4) const; _FORCE_INLINE_ Vector4 operator-(const Vector4 &p_vec4) const; _FORCE_INLINE_ Vector4 operator*(const Vector4 &p_vec4) const; _FORCE_INLINE_ Vector4 operator/(const Vector4 &p_vec4) const; _FORCE_INLINE_ Vector4 operator-() const; - _FORCE_INLINE_ Vector4 operator*(const real_t &s) const; - _FORCE_INLINE_ Vector4 operator/(const real_t &s) const; + _FORCE_INLINE_ Vector4 operator*(const real_t &p_s) const; + _FORCE_INLINE_ Vector4 operator/(const real_t &p_s) const; _FORCE_INLINE_ bool operator==(const Vector4 &p_vec4) const; _FORCE_INLINE_ bool operator!=(const Vector4 &p_vec4) const; @@ -142,28 +143,14 @@ struct _NO_DISCARD_ Vector4 { _FORCE_INLINE_ bool operator<=(const Vector4 &p_vec4) const; operator String() const; + operator Vector4i() const; _FORCE_INLINE_ Vector4() {} - - _FORCE_INLINE_ Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) : - x(p_x), - y(p_y), - z(p_z), - w(p_w) { - } - - Vector4(const Vector4 &p_vec4) : - x(p_vec4.x), - y(p_vec4.y), - z(p_vec4.z), - w(p_vec4.w) { - } - - void operator=(const Vector4 &p_vec4) { - x = p_vec4.x; - y = p_vec4.y; - z = p_vec4.z; - w = p_vec4.w; + _FORCE_INLINE_ Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) { + x = p_x; + y = p_y; + z = p_z; + w = p_w; } }; @@ -202,15 +189,15 @@ void Vector4::operator/=(const Vector4 &p_vec4) { z /= p_vec4.z; w /= p_vec4.w; } -void Vector4::operator*=(const real_t &s) { - x *= s; - y *= s; - z *= s; - w *= s; +void Vector4::operator*=(const real_t &p_s) { + x *= p_s; + y *= p_s; + z *= p_s; + w *= p_s; } -void Vector4::operator/=(const real_t &s) { - *this *= 1.0f / s; +void Vector4::operator/=(const real_t &p_s) { + *this *= 1.0f / p_s; } Vector4 Vector4::operator+(const Vector4 &p_vec4) const { @@ -233,12 +220,12 @@ Vector4 Vector4::operator-() const { return Vector4(-x, -y, -z, -w); } -Vector4 Vector4::operator*(const real_t &s) const { - return Vector4(x * s, y * s, z * s, w * s); +Vector4 Vector4::operator*(const real_t &p_s) const { + return Vector4(x * p_s, y * p_s, z * p_s, w * p_s); } -Vector4 Vector4::operator/(const real_t &s) const { - return *this * (1.0f / s); +Vector4 Vector4::operator/(const real_t &p_s) const { + return *this * (1.0f / p_s); } bool Vector4::operator==(const Vector4 &p_vec4) const { diff --git a/include/godot_cpp/variant/vector4i.hpp b/include/godot_cpp/variant/vector4i.hpp index 8e9510fd0..eaa884a7f 100644 --- a/include/godot_cpp/variant/vector4i.hpp +++ b/include/godot_cpp/variant/vector4i.hpp @@ -92,17 +92,17 @@ struct _NO_DISCARD_ Vector4i { _FORCE_INLINE_ int64_t length_squared() const; _FORCE_INLINE_ double length() const; - _FORCE_INLINE_ int64_t distance_squared_to(const Vector4i &p_to) const; - _FORCE_INLINE_ double distance_to(const Vector4i &p_to) const; - _FORCE_INLINE_ void zero(); + _FORCE_INLINE_ double distance_to(const Vector4i &p_to) const; + _FORCE_INLINE_ int64_t distance_squared_to(const Vector4i &p_to) const; + _FORCE_INLINE_ Vector4i abs() const; _FORCE_INLINE_ Vector4i sign() const; - Vector4i snapped(const Vector4i &p_step) const; - Vector4i snappedi(int32_t p_step) const; Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const; Vector4i clampi(int32_t p_min, int32_t p_max) const; + Vector4i snapped(const Vector4i &p_step) const; + Vector4i snappedi(const int32_t &p_step) const; /* Operators */ @@ -154,14 +154,14 @@ double Vector4i::length() const { return Math::sqrt((double)length_squared()); } -int64_t Vector4i::distance_squared_to(const Vector4i &p_to) const { - return (p_to - *this).length_squared(); -} - double Vector4i::distance_to(const Vector4i &p_to) const { return (p_to - *this).length(); } +int64_t Vector4i::distance_squared_to(const Vector4i &p_to) const { + return (p_to - *this).length_squared(); +} + Vector4i Vector4i::abs() const { return Vector4i(Math::abs(x), Math::abs(y), Math::abs(z), Math::abs(w)); } diff --git a/src/variant/aabb.cpp b/src/variant/aabb.cpp index ded17d2ba..c0ac63899 100644 --- a/src/variant/aabb.cpp +++ b/src/variant/aabb.cpp @@ -119,55 +119,75 @@ AABB AABB::intersection(const AABB &p_aabb) const { return AABB(min, max - min); } -bool AABB::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip, Vector3 *r_normal) const { +// Note that this routine returns the BACKTRACKED (i.e. behind the ray origin) +// intersection point + normal if INSIDE the AABB. +// The caller can therefore decide when INSIDE whether to use the +// backtracked intersection, or use p_from as the intersection, and +// carry on progressing without e.g. reflecting against the normal. +bool AABB::find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool &r_inside, Vector3 *r_intersection_point, Vector3 *r_normal) const { #ifdef MATH_CHECKS if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) { ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size."); } #endif - Vector3 c1, c2; Vector3 end = position + size; - real_t near = -1e20; - real_t far = 1e20; + real_t tmin = -1e20; + real_t tmax = 1e20; int axis = 0; + // Make sure r_inside is always initialized, + // to prevent reading uninitialized data in the client code. + r_inside = false; + for (int i = 0; i < 3; i++) { if (p_dir[i] == 0) { if ((p_from[i] < position[i]) || (p_from[i] > end[i])) { return false; } } else { // ray not parallel to planes in this direction - c1[i] = (position[i] - p_from[i]) / p_dir[i]; - c2[i] = (end[i] - p_from[i]) / p_dir[i]; + real_t t1 = (position[i] - p_from[i]) / p_dir[i]; + real_t t2 = (end[i] - p_from[i]) / p_dir[i]; - if (c1[i] > c2[i]) { - SWAP(c1, c2); + if (t1 > t2) { + SWAP(t1, t2); } - if (c1[i] > near) { - near = c1[i]; + if (t1 >= tmin) { + tmin = t1; axis = i; } - if (c2[i] < far) { - far = c2[i]; + if (t2 < tmax) { + if (t2 < 0) { + return false; + } + tmax = t2; } - if ((near > far) || (far < 0)) { + if (tmin > tmax) { return false; } } } - if (r_clip) { - *r_clip = c1; + // Did the ray start from inside the box? + // In which case the intersection returned is the point of entry + // (behind the ray start) or the calling routine can use the ray origin as intersection point. + r_inside = tmin < 0; + + if (r_intersection_point) { + *r_intersection_point = p_from + p_dir * tmin; + + // Prevent float error by making sure the point is exactly + // on the AABB border on the relevant axis. + r_intersection_point->coord[axis] = (p_dir[axis] >= 0) ? position.coord[axis] : end.coord[axis]; } if (r_normal) { *r_normal = Vector3(); - (*r_normal)[axis] = p_dir[axis] ? -1 : 1; + (*r_normal)[axis] = (p_dir[axis] >= 0) ? -1 : 1; } return true; } -bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip, Vector3 *r_normal) const { +bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_intersection_point, Vector3 *r_normal) const { #ifdef MATH_CHECKS if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) { ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size."); @@ -225,8 +245,8 @@ bool AABB::intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector *r_normal = normal; } - if (r_clip) { - *r_clip = p_from + rel * min; + if (r_intersection_point) { + *r_intersection_point = p_from + rel * min; } return true; @@ -412,7 +432,15 @@ Variant AABB::intersects_segment_bind(const Vector3 &p_from, const Vector3 &p_to Variant AABB::intersects_ray_bind(const Vector3 &p_from, const Vector3 &p_dir) const { Vector3 inters; - if (intersects_ray(p_from, p_dir, &inters)) { + bool inside = false; + + if (find_intersects_ray(p_from, p_dir, inside, &inters)) { + // When inside the intersection point may be BEHIND the ray, + // so for general use we return the ray origin. + if (inside) { + return p_from; + } + return inters; } return Variant(); diff --git a/src/variant/basis.cpp b/src/variant/basis.cpp index d8a991917..b79f3dd5a 100644 --- a/src/variant/basis.cpp +++ b/src/variant/basis.cpp @@ -37,23 +37,6 @@ namespace godot { -void Basis::from_z(const Vector3 &p_z) { - if (Math::abs(p_z.z) > (real_t)Math_SQRT12) { - // choose p in y-z plane - real_t a = p_z[1] * p_z[1] + p_z[2] * p_z[2]; - real_t k = 1.0f / Math::sqrt(a); - rows[0] = Vector3(0, -p_z[2] * k, p_z[1] * k); - rows[1] = Vector3(a * k, -p_z[0] * rows[0][2], p_z[0] * rows[0][1]); - } else { - // choose p in x-y plane - real_t a = p_z.x * p_z.x + p_z.y * p_z.y; - real_t k = 1.0f / Math::sqrt(a); - rows[0] = Vector3(-p_z.y * k, p_z.x * k, 0); - rows[1] = Vector3(-p_z.z * rows[0].y, p_z.z * rows[0].x, a * k); - } - rows[2] = p_z; -} - void Basis::invert() { real_t co[3] = { cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1) @@ -107,13 +90,35 @@ Basis Basis::orthogonalized() const { return c; } +// Returns true if the basis vectors are orthogonal (perpendicular), so it has no skew or shear, and can be decomposed into rotation and scale. +// See https://en.wikipedia.org/wiki/Orthogonal_basis bool Basis::is_orthogonal() const { - Basis identity; - Basis m = (*this) * transposed(); + const Vector3 x = get_column(0); + const Vector3 y = get_column(1); + const Vector3 z = get_column(2); + return Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z)); +} - return m.is_equal_approx(identity); +// Returns true if the basis vectors are orthonormal (orthogonal and normalized), so it has no scale, skew, or shear. +// See https://en.wikipedia.org/wiki/Orthonormal_basis +bool Basis::is_orthonormal() const { + const Vector3 x = get_column(0); + const Vector3 y = get_column(1); + const Vector3 z = get_column(2); + return Math::is_equal_approx(x.length_squared(), 1) && Math::is_equal_approx(y.length_squared(), 1) && Math::is_equal_approx(z.length_squared(), 1) && Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z)); } +// Returns true if the basis is conformal (orthogonal, uniform scale, preserves angles and distance ratios). +// See https://en.wikipedia.org/wiki/Conformal_linear_transformation +bool Basis::is_conformal() const { + const Vector3 x = get_column(0); + const Vector3 y = get_column(1); + const Vector3 z = get_column(2); + const real_t x_len_sq = x.length_squared(); + return Math::is_equal_approx(x_len_sq, y.length_squared()) && Math::is_equal_approx(x_len_sq, z.length_squared()) && Math::is_zero_approx(x.dot(y)) && Math::is_zero_approx(x.dot(z)) && Math::is_zero_approx(y.dot(z)); +} + +// Returns true if the basis only has diagonal elements, so it may only have scale or flip, but no rotation, skew, or shear. bool Basis::is_diagonal() const { return ( Math::is_zero_approx(rows[0][1]) && Math::is_zero_approx(rows[0][2]) && @@ -121,8 +126,9 @@ bool Basis::is_diagonal() const { Math::is_zero_approx(rows[2][0]) && Math::is_zero_approx(rows[2][1])); } +// Returns true if the basis is a pure rotation matrix, so it has no scale, skew, shear, or flip. bool Basis::is_rotation() const { - return Math::is_equal_approx(determinant(), 1, (real_t)UNIT_EPSILON) && is_orthogonal(); + return is_conformal() && Math::is_equal_approx(determinant(), 1, (real_t)UNIT_EPSILON); } #ifdef MATH_CHECKS @@ -257,29 +263,26 @@ void Basis::scale_orthogonal(const Vector3 &p_scale) { Basis Basis::scaled_orthogonal(const Vector3 &p_scale) const { Basis m = *this; Vector3 s = Vector3(-1, -1, -1) + p_scale; + bool sign = Math::sign(s.x + s.y + s.z); + Basis b = m.orthonormalized(); + s = b.xform_inv(s); Vector3 dots; - Basis b; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { - dots[j] += s[i] * Math::abs(m.get_column(i).normalized().dot(b.get_column(j))); + dots[j] += s[i] * abs(m.get_column(i).normalized().dot(b.get_column(j))); } } + if (sign != Math::sign(dots.x + dots.y + dots.z)) { + dots = -dots; + } m.scale_local(Vector3(1, 1, 1) + dots); return m; } -float Basis::get_uniform_scale() const { +real_t Basis::get_uniform_scale() const { return (rows[0].length() + rows[1].length() + rows[2].length()) / 3.0f; } -void Basis::make_scale_uniform() { - float l = (rows[0].length() + rows[1].length() + rows[2].length()) / 3.0f; - for (int i = 0; i < 3; i++) { - rows[i].normalize(); - rows[i] *= l; - } -} - Basis Basis::scaled_local(const Vector3 &p_scale) const { return (*this) * Basis::from_scale(p_scale); } @@ -291,7 +294,7 @@ Vector3 Basis::get_scale_abs() const { Vector3(rows[0][2], rows[1][2], rows[2][2]).length()); } -Vector3 Basis::get_scale_local() const { +Vector3 Basis::get_scale_global() const { real_t det_sign = SIGN(determinant()); return det_sign * Vector3(rows[0].length(), rows[1].length(), rows[2].length()); } @@ -418,7 +421,7 @@ void Basis::rotate_to_align(Vector3 p_start_direction, Vector3 p_end_direction) real_t dot = p_start_direction.dot(p_end_direction); dot = CLAMP(dot, -1.0f, 1.0f); const real_t angle_rads = Math::acos(dot); - set_axis_angle(axis, angle_rads); + *this = Basis(axis, angle_rads) * (*this); } } @@ -584,7 +587,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { euler.z = Math_PI / 2.0f; } return euler; - } + } break; case EULER_ORDER_ZXY: { // Euler angles in ZXY convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix @@ -612,7 +615,7 @@ Vector3 Basis::get_euler(EulerOrder p_order) const { euler.z = 0; } return euler; - } + } break; case EULER_ORDER_ZYX: { // Euler angles in ZYX convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix @@ -683,7 +686,7 @@ void Basis::set_euler(const Vector3 &p_euler, EulerOrder p_order) { *this = zmat * ymat * xmat; } break; default: { - ERR_FAIL_MSG("Invalid order parameter for set_euler(vec3,order)"); + ERR_FAIL_MSG("Invalid Euler order parameter."); } } } @@ -720,7 +723,7 @@ Basis::operator String() const { Quaternion Basis::get_quaternion() const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis must be normalized in order to be casted to a Quaternion. Use get_rotation_quaternion() or call orthonormalized() if the Basis contains linearly independent vectors."); + ERR_FAIL_COND_V_MSG(!is_rotation(), Quaternion(), "Basis " + operator String() + " must be normalized in order to be casted to a Quaternion. Use get_rotation_quaternion() or call orthonormalized() if the Basis contains linearly independent vectors."); #endif /* Allow getting a quaternion from an unnormalized transform */ Basis m = *this; @@ -828,8 +831,8 @@ void Basis::get_axis_angle(Vector3 &r_axis, real_t &r_angle) const { z = (rows[1][0] - rows[0][1]) / s; r_axis = Vector3(x, y, z); - // CLAMP to avoid NaN if the value passed to acos is not in [0,1]. - r_angle = Math::acos(CLAMP((rows[0][0] + rows[1][1] + rows[2][2] - 1) / 2, (real_t)0.0, (real_t)1.0)); + // acos does clamping. + r_angle = Math::acos((rows[0][0] + rows[1][1] + rows[2][2] - 1) / 2); } void Basis::set_quaternion(const Quaternion &p_quaternion) { @@ -847,7 +850,7 @@ void Basis::set_quaternion(const Quaternion &p_quaternion) { void Basis::set_axis_angle(const Vector3 &p_axis, real_t p_angle) { // Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_angle #ifdef MATH_CHECKS - ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized."); + ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 " + p_axis.operator String() + " must be normalized."); #endif Vector3 axis_sq(p_axis.x * p_axis.x, p_axis.y * p_axis.y, p_axis.z * p_axis.z); real_t cosine = Math::cos(p_angle); diff --git a/src/variant/color.cpp b/src/variant/color.cpp index 4e3b870e2..a398047cc 100644 --- a/src/variant/color.cpp +++ b/src/variant/color.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include namespace godot { @@ -131,11 +132,11 @@ String _to_hex(float p_val) { String Color::to_html(bool p_alpha) const { String txt; - txt = txt + _to_hex(r); - txt = txt + _to_hex(g); - txt = txt + _to_hex(b); + txt += _to_hex(r); + txt += _to_hex(g); + txt += _to_hex(b); if (p_alpha) { - txt = txt + _to_hex(a); + txt += _to_hex(a); } return txt; } @@ -240,6 +241,19 @@ void Color::set_hsv(float p_h, float p_s, float p_v, float p_alpha) { } } +void Color::set_ok_hsl(float p_h, float p_s, float p_l, float p_alpha) { + ok_color::HSL hsl; + hsl.h = p_h; + hsl.s = p_s; + hsl.l = p_l; + ok_color::RGB rgb = ok_color::okhsl_to_srgb(hsl); + Color c = Color(rgb.r, rgb.g, rgb.b, p_alpha).clamp(); + r = c.r; + g = c.g; + b = c.b; + a = c.a; +} + bool Color::is_equal_approx(const Color &p_color) const { return Math::is_equal_approx(r, p_color.r) && Math::is_equal_approx(g, p_color.g) && Math::is_equal_approx(b, p_color.b) && Math::is_equal_approx(a, p_color.a); } @@ -385,7 +399,6 @@ Color Color::named(const String &p_name) { int idx = find_named_color(p_name); if (idx == -1) { ERR_FAIL_V_MSG(Color(), "Invalid color name: " + p_name + "."); - return Color(); } return named_colors[idx].color; } @@ -400,7 +413,7 @@ Color Color::named(const String &p_name, const Color &p_default) { int Color::find_named_color(const String &p_name) { String name = p_name; - // Normalize name + // Normalize name. name = name.replace(" ", ""); name = name.replace("-", ""); name = name.replace("_", ""); @@ -569,4 +582,46 @@ Color Color::operator-() const { 1.0f - a); } +Color Color::from_ok_hsl(float p_h, float p_s, float p_l, float p_alpha) { + Color c; + c.set_ok_hsl(p_h, p_s, p_l, p_alpha); + return c; +} + +float Color::get_ok_hsl_h() const { + ok_color::RGB rgb; + rgb.r = r; + rgb.g = g; + rgb.b = b; + ok_color::HSL ok_hsl = ok_color::srgb_to_okhsl(rgb); + if (Math::is_nan(ok_hsl.h)) { + return 0.0f; + } + return CLAMP(ok_hsl.h, 0.0f, 1.0f); +} + +float Color::get_ok_hsl_s() const { + ok_color::RGB rgb; + rgb.r = r; + rgb.g = g; + rgb.b = b; + ok_color::HSL ok_hsl = ok_color::srgb_to_okhsl(rgb); + if (Math::is_nan(ok_hsl.s)) { + return 0.0f; + } + return CLAMP(ok_hsl.s, 0.0f, 1.0f); +} + +float Color::get_ok_hsl_l() const { + ok_color::RGB rgb; + rgb.r = r; + rgb.g = g; + rgb.b = b; + ok_color::HSL ok_hsl = ok_color::srgb_to_okhsl(rgb); + if (Math::is_nan(ok_hsl.l)) { + return 0.0f; + } + return CLAMP(ok_hsl.l, 0.0f, 1.0f); +} + } // namespace godot diff --git a/src/variant/plane.cpp b/src/variant/plane.cpp index caea516e1..9b72c7af2 100644 --- a/src/variant/plane.cpp +++ b/src/variant/plane.cpp @@ -100,13 +100,11 @@ bool Plane::intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 Vector3 segment = p_dir; real_t den = normal.dot(segment); - //printf("den is %i\n",den); if (Math::is_zero_approx(den)) { return false; } real_t dist = (normal.dot(p_from) - d) / den; - //printf("dist is %i\n",dist); if (dist > (real_t)CMP_EPSILON) { //this is a ray, before the emitting pos (p_from) doesn't exist @@ -123,13 +121,11 @@ bool Plane::intersects_segment(const Vector3 &p_begin, const Vector3 &p_end, Vec Vector3 segment = p_begin - p_end; real_t den = normal.dot(segment); - //printf("den is %i\n",den); if (Math::is_zero_approx(den)) { return false; } real_t dist = (normal.dot(p_begin) - d) / den; - //printf("dist is %i\n",dist); if (dist < (real_t)-CMP_EPSILON || dist > (1.0f + (real_t)CMP_EPSILON)) { return false; diff --git a/src/variant/projection.cpp b/src/variant/projection.cpp index ddedc93f9..fe0f799be 100644 --- a/src/variant/projection.cpp +++ b/src/variant/projection.cpp @@ -39,7 +39,7 @@ namespace godot { -float Projection::determinant() const { +real_t Projection::determinant() const { return columns[0][3] * columns[1][2] * columns[2][1] * columns[3][0] - columns[0][2] * columns[1][3] * columns[2][1] * columns[3][0] - columns[0][3] * columns[1][1] * columns[2][2] * columns[3][0] + columns[0][1] * columns[1][3] * columns[2][2] * columns[3][0] + columns[0][2] * columns[1][1] * columns[2][3] * columns[3][0] - columns[0][1] * columns[1][2] * columns[2][3] * columns[3][0] - @@ -171,7 +171,7 @@ Projection Projection::perspective_znear_adjusted(real_t p_new_znear) const { } Plane Projection::get_projection_plane(Planes p_plane) const { - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; switch (p_plane) { case PLANE_NEAR: { @@ -404,20 +404,19 @@ void Projection::set_frustum(real_t p_size, real_t p_aspect, Vector2 p_offset, r } real_t Projection::get_z_far() const { - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; Plane new_plane = Plane(matrix[3] - matrix[2], matrix[7] - matrix[6], matrix[11] - matrix[10], matrix[15] - matrix[14]); - new_plane.normal = -new_plane.normal; new_plane.normalize(); return new_plane.d; } real_t Projection::get_z_near() const { - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; Plane new_plane = Plane(matrix[3] + matrix[2], matrix[7] + matrix[6], matrix[11] + matrix[10], @@ -428,7 +427,7 @@ real_t Projection::get_z_near() const { } Vector2 Projection::get_viewport_half_extents() const { - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; ///////--- Near Plane ---/////// Plane near_plane = Plane(matrix[3] + matrix[2], matrix[7] + matrix[6], @@ -456,7 +455,7 @@ Vector2 Projection::get_viewport_half_extents() const { } Vector2 Projection::get_far_plane_half_extents() const { - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; ///////--- Far Plane ---/////// Plane far_plane = Plane(matrix[3] - matrix[2], matrix[7] - matrix[6], @@ -519,7 +518,7 @@ Array Projection::get_projection_planes(const Transform3D &p_transform) const { Array planes; planes.resize(6); - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; Plane new_plane; @@ -599,101 +598,229 @@ Projection Projection::inverse() const { } void Projection::invert() { - int i, j, k; - int pvt_i[4], pvt_j[4]; /* Locations of pivot matrix */ - real_t pvt_val; /* Value of current pivot element */ - real_t hold; /* Temporary storage */ - real_t determinant = 1.0f; - for (k = 0; k < 4; k++) { - /** Locate k'th pivot element **/ - pvt_val = columns[k][k]; /** Initialize for search **/ - pvt_i[k] = k; - pvt_j[k] = k; - for (i = k; i < 4; i++) { - for (j = k; j < 4; j++) { - if (Math::abs(columns[i][j]) > Math::abs(pvt_val)) { - pvt_i[k] = i; - pvt_j[k] = j; - pvt_val = columns[i][j]; - } - } - } - - /** Product of pivots, gives determinant when finished **/ - determinant *= pvt_val; - if (Math::is_zero_approx(determinant)) { - return; /** Matrix is singular (zero determinant). **/ - } - - /** "Interchange" rows (with sign change stuff) **/ - i = pvt_i[k]; - if (i != k) { /** If rows are different **/ - for (j = 0; j < 4; j++) { - hold = -columns[k][j]; - columns[k][j] = columns[i][j]; - columns[i][j] = hold; - } - } - - /** "Interchange" columns **/ - j = pvt_j[k]; - if (j != k) { /** If columns are different **/ - for (i = 0; i < 4; i++) { - hold = -columns[i][k]; - columns[i][k] = columns[i][j]; - columns[i][j] = hold; - } - } - - /** Divide column by minus pivot value **/ - for (i = 0; i < 4; i++) { - if (i != k) { - columns[i][k] /= (-pvt_val); - } - } - - /** Reduce the matrix **/ - for (i = 0; i < 4; i++) { - hold = columns[i][k]; - for (j = 0; j < 4; j++) { - if (i != k && j != k) { - columns[i][j] += hold * columns[k][j]; - } - } - } - - /** Divide row by pivot **/ - for (j = 0; j < 4; j++) { - if (j != k) { - columns[k][j] /= pvt_val; - } - } - - /** Replace pivot by reciprocal (at last we can touch it). **/ - columns[k][k] = 1.0 / pvt_val; + // Adapted from Mesa's `src/util/u_math.c` `util_invert_mat4x4`. + // MIT licensed. Copyright 2008 VMware, Inc. Authored by Jacques Leroy. + Projection temp; + real_t *out = (real_t *)temp.columns; + real_t *m = (real_t *)columns; + + real_t wtmp[4][8]; + real_t m0, m1, m2, m3, s; + real_t *r0, *r1, *r2, *r3; + +#define MAT(m, r, c) (m)[(c) * 4 + (r)] + + r0 = wtmp[0]; + r1 = wtmp[1]; + r2 = wtmp[2]; + r3 = wtmp[3]; + + r0[0] = MAT(m, 0, 0); + r0[1] = MAT(m, 0, 1); + r0[2] = MAT(m, 0, 2); + r0[3] = MAT(m, 0, 3); + r0[4] = 1.0; + r0[5] = 0.0; + r0[6] = 0.0; + r0[7] = 0.0; + + r1[0] = MAT(m, 1, 0); + r1[1] = MAT(m, 1, 1); + r1[2] = MAT(m, 1, 2); + r1[3] = MAT(m, 1, 3); + r1[5] = 1.0; + r1[4] = 0.0; + r1[6] = 0.0; + r1[7] = 0.0; + + r2[0] = MAT(m, 2, 0); + r2[1] = MAT(m, 2, 1); + r2[2] = MAT(m, 2, 2); + r2[3] = MAT(m, 2, 3); + r2[6] = 1.0; + r2[4] = 0.0; + r2[5] = 0.0; + r2[7] = 0.0; + + r3[0] = MAT(m, 3, 0); + r3[1] = MAT(m, 3, 1); + r3[2] = MAT(m, 3, 2); + r3[3] = MAT(m, 3, 3); + + r3[7] = 1.0; + r3[4] = 0.0; + r3[5] = 0.0; + r3[6] = 0.0; + + /* choose pivot - or die */ + if (Math::abs(r3[0]) > Math::abs(r2[0])) { + SWAP(r3, r2); + } + if (Math::abs(r2[0]) > Math::abs(r1[0])) { + SWAP(r2, r1); + } + if (Math::abs(r1[0]) > Math::abs(r0[0])) { + SWAP(r1, r0); + } + ERR_FAIL_COND(0.0 == r0[0]); + + /* eliminate first variable */ + m1 = r1[0] / r0[0]; + m2 = r2[0] / r0[0]; + m3 = r3[0] / r0[0]; + s = r0[1]; + r1[1] -= m1 * s; + r2[1] -= m2 * s; + r3[1] -= m3 * s; + s = r0[2]; + r1[2] -= m1 * s; + r2[2] -= m2 * s; + r3[2] -= m3 * s; + s = r0[3]; + r1[3] -= m1 * s; + r2[3] -= m2 * s; + r3[3] -= m3 * s; + s = r0[4]; + if (s != 0.0) { + r1[4] -= m1 * s; + r2[4] -= m2 * s; + r3[4] -= m3 * s; + } + s = r0[5]; + if (s != 0.0) { + r1[5] -= m1 * s; + r2[5] -= m2 * s; + r3[5] -= m3 * s; + } + s = r0[6]; + if (s != 0.0) { + r1[6] -= m1 * s; + r2[6] -= m2 * s; + r3[6] -= m3 * s; + } + s = r0[7]; + if (s != 0.0) { + r1[7] -= m1 * s; + r2[7] -= m2 * s; + r3[7] -= m3 * s; } - /* That was most of the work, one final pass of row/column interchange */ - /* to finish */ - for (k = 4 - 2; k >= 0; k--) { /* Don't need to work with 1 by 1 corner*/ - i = pvt_j[k]; /* Rows to swap correspond to pivot COLUMN */ - if (i != k) { /* If rows are different */ - for (j = 0; j < 4; j++) { - hold = columns[k][j]; - columns[k][j] = -columns[i][j]; - columns[i][j] = hold; - } - } + /* choose pivot - or die */ + if (Math::abs(r3[1]) > Math::abs(r2[1])) { + SWAP(r3, r2); + } + if (Math::abs(r2[1]) > Math::abs(r1[1])) { + SWAP(r2, r1); + } + ERR_FAIL_COND(0.0 == r1[1]); + + /* eliminate second variable */ + m2 = r2[1] / r1[1]; + m3 = r3[1] / r1[1]; + r2[2] -= m2 * r1[2]; + r3[2] -= m3 * r1[2]; + r2[3] -= m2 * r1[3]; + r3[3] -= m3 * r1[3]; + s = r1[4]; + if (0.0 != s) { + r2[4] -= m2 * s; + r3[4] -= m3 * s; + } + s = r1[5]; + if (0.0 != s) { + r2[5] -= m2 * s; + r3[5] -= m3 * s; + } + s = r1[6]; + if (0.0 != s) { + r2[6] -= m2 * s; + r3[6] -= m3 * s; + } + s = r1[7]; + if (0.0 != s) { + r2[7] -= m2 * s; + r3[7] -= m3 * s; + } - j = pvt_i[k]; /* Columns to swap correspond to pivot ROW */ - if (j != k) { /* If columns are different */ - for (i = 0; i < 4; i++) { - hold = columns[i][k]; - columns[i][k] = -columns[i][j]; - columns[i][j] = hold; - } - } + /* choose pivot - or die */ + if (Math::abs(r3[2]) > Math::abs(r2[2])) { + SWAP(r3, r2); } + ERR_FAIL_COND(0.0 == r2[2]); + + /* eliminate third variable */ + m3 = r3[2] / r2[2]; + r3[3] -= m3 * r2[3]; + r3[4] -= m3 * r2[4]; + r3[5] -= m3 * r2[5]; + r3[6] -= m3 * r2[6]; + r3[7] -= m3 * r2[7]; + + /* last check */ + ERR_FAIL_COND(0.0 == r3[3]); + + s = 1.0 / r3[3]; /* now back substitute row 3 */ + r3[4] *= s; + r3[5] *= s; + r3[6] *= s; + r3[7] *= s; + + m2 = r2[3]; /* now back substitute row 2 */ + s = 1.0 / r2[2]; + r2[4] = s * (r2[4] - r3[4] * m2); + r2[5] = s * (r2[5] - r3[5] * m2); + r2[6] = s * (r2[6] - r3[6] * m2); + r2[7] = s * (r2[7] - r3[7] * m2); + m1 = r1[3]; + r1[4] -= r3[4] * m1; + r1[5] -= r3[5] * m1; + r1[6] -= r3[6] * m1; + r1[7] -= r3[7] * m1; + m0 = r0[3]; + r0[4] -= r3[4] * m0; + r0[5] -= r3[5] * m0; + r0[6] -= r3[6] * m0; + r0[7] -= r3[7] * m0; + + m1 = r1[2]; /* now back substitute row 1 */ + s = 1.0 / r1[1]; + r1[4] = s * (r1[4] - r2[4] * m1); + r1[5] = s * (r1[5] - r2[5] * m1), + r1[6] = s * (r1[6] - r2[6] * m1); + r1[7] = s * (r1[7] - r2[7] * m1); + m0 = r0[2]; + r0[4] -= r2[4] * m0; + r0[5] -= r2[5] * m0; + r0[6] -= r2[6] * m0; + r0[7] -= r2[7] * m0; + + m0 = r0[1]; /* now back substitute row 0 */ + s = 1.0 / r0[0]; + r0[4] = s * (r0[4] - r1[4] * m0); + r0[5] = s * (r0[5] - r1[5] * m0), + r0[6] = s * (r0[6] - r1[6] * m0); + r0[7] = s * (r0[7] - r1[7] * m0); + + MAT(out, 0, 0) = r0[4]; + MAT(out, 0, 1) = r0[5]; + MAT(out, 0, 2) = r0[6]; + MAT(out, 0, 3) = r0[7]; + MAT(out, 1, 0) = r1[4]; + MAT(out, 1, 1) = r1[5]; + MAT(out, 1, 2) = r1[6]; + MAT(out, 1, 3) = r1[7]; + MAT(out, 2, 0) = r2[4]; + MAT(out, 2, 1) = r2[5]; + MAT(out, 2, 2) = r2[6]; + MAT(out, 2, 3) = r2[7]; + MAT(out, 3, 0) = r3[4]; + MAT(out, 3, 1) = r3[5]; + MAT(out, 3, 2) = r3[6]; + MAT(out, 3, 3) = r3[7]; + +#undef MAT + + *this = temp; } void Projection::flip_y() { @@ -722,7 +849,8 @@ Projection Projection::operator*(const Projection &p_matrix) const { return new_matrix; } -void Projection::set_depth_correction(bool p_flip_y) { +void Projection::set_depth_correction(bool p_flip_y, bool p_reverse_z, bool p_remap_z) { + // p_remap_z is used to convert from OpenGL-style clip space (-1 - 1) to Vulkan style (0 - 1). real_t *m = &columns[0][0]; m[0] = 1; @@ -735,11 +863,11 @@ void Projection::set_depth_correction(bool p_flip_y) { m[7] = 0.0; m[8] = 0.0; m[9] = 0.0; - m[10] = 0.5; + m[10] = p_remap_z ? (p_reverse_z ? -0.5 : 0.5) : (p_reverse_z ? -1.0 : 1.0); m[11] = 0.0; m[12] = 0.0; m[13] = 0.0; - m[14] = 0.5; + m[14] = p_remap_z ? 0.5 : 0.0; m[15] = 1.0; } @@ -789,7 +917,7 @@ Projection::operator String() const { String str; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { - str = str + String((j > 0) ? ", " : "\n") + rtos(columns[i][j]); + str += String((j > 0) ? ", " : "\n") + rtos(columns[i][j]); } } @@ -812,7 +940,7 @@ bool Projection::is_orthogonal() const { } real_t Projection::get_fov() const { - const real_t *matrix = (const real_t *)this->columns; + const real_t *matrix = (const real_t *)columns; Plane right_plane = Plane(matrix[3] - matrix[0], matrix[7] - matrix[4], @@ -834,13 +962,13 @@ real_t Projection::get_fov() const { } } -float Projection::get_lod_multiplier() const { +real_t Projection::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); + const real_t zn = get_z_near(); + const real_t width = get_viewport_half_extents().x * 2.0f; + return 1.0f / (zn / width); } // Usage is lod_size / (lod_distance * multiplier) < threshold diff --git a/src/variant/quaternion.cpp b/src/variant/quaternion.cpp index c01085051..108838767 100644 --- a/src/variant/quaternion.cpp +++ b/src/variant/quaternion.cpp @@ -37,28 +37,15 @@ namespace godot { real_t Quaternion::angle_to(const Quaternion &p_to) const { real_t d = dot(p_to); - return Math::acos(CLAMP(d * d * 2 - 1, -1, 1)); + // acos does clamping. + return Math::acos(d * d * 2 - 1); } -// get_euler_xyz returns a vector containing the Euler angles in the format -// (ax,ay,az), where ax is the angle of rotation around x axis, -// and similar for other axes. -// This implementation uses XYZ convention (Z is the first rotation). -Vector3 Quaternion::get_euler_xyz() const { - Basis m(*this); - return m.get_euler(EULER_ORDER_XYZ); -} - -// get_euler_yxz returns a vector containing the Euler angles in the format -// (ax,ay,az), where ax is the angle of rotation around x axis, -// and similar for other axes. -// This implementation uses YXZ convention (Z is the first rotation). -Vector3 Quaternion::get_euler_yxz() const { +Vector3 Quaternion::get_euler(EulerOrder p_order) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), Vector3(0, 0, 0), "The quaternion " + operator String() + " must be normalized."); #endif - Basis m(*this); - return m.get_euler(EULER_ORDER_YXZ); + return Basis(*this).get_euler(p_order); } void Quaternion::operator*=(const Quaternion &p_q) { @@ -103,7 +90,7 @@ bool Quaternion::is_normalized() const { Quaternion Quaternion::inverse() const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The quaternion " + operator String() + " must be normalized."); #endif return Quaternion(-x, -y, -z, w); } @@ -127,8 +114,8 @@ Quaternion Quaternion::exp() const { Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized."); - ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized."); + ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion " + p_to.operator String() + " must be normalized."); #endif Quaternion to1; real_t omega, cosom, sinom, scale0, scale1; @@ -168,8 +155,8 @@ Quaternion Quaternion::slerp(const Quaternion &p_to, const real_t &p_weight) con Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized."); - ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized."); + ERR_FAIL_COND_V_MSG(!p_to.is_normalized(), Quaternion(), "The end quaternion " + p_to.operator String() + " must be normalized."); #endif const Quaternion &from = *this; @@ -192,8 +179,8 @@ Quaternion Quaternion::slerpni(const Quaternion &p_to, const real_t &p_weight) c Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized."); - ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized."); + ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion " + p_b.operator String() + " must be normalized."); #endif Quaternion from_q = *this; Quaternion pre_q = p_pre_a; @@ -236,15 +223,15 @@ Quaternion Quaternion::spherical_cubic_interpolate(const Quaternion &p_b, const ln.z = Math::cubic_interpolate(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight); Quaternion q2 = to_q * ln.exp(); - // To cancel error made by Expmap ambiguity, do blends. + // To cancel error made by Expmap ambiguity, do blending. return q1.slerp(q2, p_weight); } Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b, const Quaternion &p_pre_a, const Quaternion &p_post_b, const real_t &p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion must be normalized."); - ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion must be normalized."); + ERR_FAIL_COND_V_MSG(!is_normalized(), Quaternion(), "The start quaternion " + operator String() + " must be normalized."); + ERR_FAIL_COND_V_MSG(!p_b.is_normalized(), Quaternion(), "The end quaternion " + p_b.operator String() + " must be normalized."); #endif Quaternion from_q = *this; Quaternion pre_q = p_pre_a; @@ -287,7 +274,7 @@ Quaternion Quaternion::spherical_cubic_interpolate_in_time(const Quaternion &p_b ln.z = Math::cubic_interpolate_in_time(ln_from.z, ln_to.z, ln_pre.z, ln_post.z, p_weight, p_b_t, p_pre_a_t, p_post_b_t); Quaternion q2 = to_q * ln.exp(); - // To cancel error made by Expmap ambiguity, do blends. + // To cancel error made by Expmap ambiguity, do blending. return q1.slerp(q2, p_weight); } @@ -309,7 +296,7 @@ real_t Quaternion::get_angle() const { Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) { #ifdef MATH_CHECKS - ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 must be normalized."); + ERR_FAIL_COND_MSG(!p_axis.is_normalized(), "The axis Vector3 " + p_axis.operator String() + " must be normalized."); #endif real_t d = p_axis.length(); if (d == 0) { @@ -332,7 +319,7 @@ Quaternion::Quaternion(const Vector3 &p_axis, real_t p_angle) { // (ax, ay, az), where ax is the angle of rotation around x axis, // and similar for other axes. // This implementation uses YXZ convention (Z is the first rotation). -Quaternion::Quaternion(const Vector3 &p_euler) { +Quaternion Quaternion::from_euler(const Vector3 &p_euler) { real_t half_a1 = p_euler.y * 0.5f; real_t half_a2 = p_euler.x * 0.5f; real_t half_a3 = p_euler.z * 0.5f; @@ -348,10 +335,11 @@ Quaternion::Quaternion(const Vector3 &p_euler) { real_t cos_a3 = Math::cos(half_a3); real_t sin_a3 = Math::sin(half_a3); - x = sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3; - y = sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3; - z = -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3; - w = sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3; + return Quaternion( + sin_a1 * cos_a2 * sin_a3 + cos_a1 * sin_a2 * cos_a3, + sin_a1 * cos_a2 * cos_a3 - cos_a1 * sin_a2 * sin_a3, + -sin_a1 * sin_a2 * cos_a3 + cos_a1 * cos_a2 * sin_a3, + sin_a1 * sin_a2 * sin_a3 + cos_a1 * cos_a2 * cos_a3); } } // namespace godot diff --git a/src/variant/transform2d.cpp b/src/variant/transform2d.cpp index 3b2c0b09e..a6b1c73ec 100644 --- a/src/variant/transform2d.cpp +++ b/src/variant/transform2d.cpp @@ -48,7 +48,7 @@ Transform2D Transform2D::inverse() const { } void Transform2D::affine_invert() { - real_t det = basis_determinant(); + real_t det = determinant(); #ifdef MATH_CHECKS ERR_FAIL_COND(det == 0); #endif @@ -72,13 +72,13 @@ void Transform2D::rotate(const real_t p_angle) { } real_t Transform2D::get_skew() const { - real_t det = basis_determinant(); - return Math::acos(columns[0].normalized().dot(SIGN(det) * columns[1].normalized())) - (real_t)Math_PI * 0.5f; + real_t det = determinant(); + return Math::acos(columns[0].normalized().dot(Math::sign(det) * columns[1].normalized())) - (real_t)Math_PI * 0.5f; } void Transform2D::set_skew(const real_t p_angle) { - real_t det = basis_determinant(); - columns[1] = SIGN(det) * columns[0].rotated(((real_t)Math_PI * 0.5f + p_angle)).normalized() * columns[1].length(); + real_t det = determinant(); + columns[1] = Math::sign(det) * columns[0].rotated(((real_t)Math_PI * 0.5f + p_angle)).normalized() * columns[1].length(); } real_t Transform2D::get_rotation() const { @@ -115,7 +115,7 @@ Transform2D::Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t } Size2 Transform2D::get_scale() const { - real_t det_sign = Math::sign(basis_determinant()); + real_t det_sign = Math::sign(determinant()); return Size2(columns[0].length(), det_sign * columns[1].length()); } @@ -153,7 +153,7 @@ void Transform2D::orthonormalize() { Vector2 y = columns[1]; x.normalize(); - y = (y - x * (x.dot(y))); + y = y - x * x.dot(y); y.normalize(); columns[0] = x; @@ -161,9 +161,21 @@ void Transform2D::orthonormalize() { } Transform2D Transform2D::orthonormalized() const { - Transform2D on = *this; - on.orthonormalize(); - return on; + Transform2D ortho = *this; + ortho.orthonormalize(); + return ortho; +} + +bool Transform2D::is_conformal() const { + // Non-flipped case. + if (Math::is_equal_approx(columns[0][0], columns[1][1]) && Math::is_equal_approx(columns[0][1], -columns[1][0])) { + return true; + } + // Flipped case. + if (Math::is_equal_approx(columns[0][0], -columns[1][1]) && Math::is_equal_approx(columns[0][1], columns[1][0])) { + return true; + } + return false; } bool Transform2D::is_equal_approx(const Transform2D &p_transform) const { @@ -223,12 +235,6 @@ Transform2D Transform2D::operator*(const Transform2D &p_transform) const { return t; } -Transform2D Transform2D::basis_scaled(const Size2 &p_scale) const { - Transform2D copy = *this; - copy.scale_basis(p_scale); - return copy; -} - Transform2D Transform2D::scaled(const Size2 &p_scale) const { // Equivalent to left multiplication Transform2D copy = *this; @@ -267,43 +273,16 @@ Transform2D Transform2D::rotated_local(const real_t p_angle) const { return (*this) * Transform2D(p_angle, Vector2()); // Could be optimized, because origin transform can be skipped. } -real_t Transform2D::basis_determinant() const { +real_t Transform2D::determinant() const { return columns[0].x * columns[1].y - columns[0].y * columns[1].x; } -Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, const real_t p_c) const { - //extract parameters - Vector2 p1 = get_origin(); - Vector2 p2 = p_transform.get_origin(); - - real_t r1 = get_rotation(); - real_t r2 = p_transform.get_rotation(); - - Size2 s1 = get_scale(); - Size2 s2 = p_transform.get_scale(); - - //slerp rotation - Vector2 v1(Math::cos(r1), Math::sin(r1)); - Vector2 v2(Math::cos(r2), Math::sin(r2)); - - real_t dot = v1.dot(v2); - - dot = Math::clamp(dot, (real_t)-1.0, (real_t)1.0); - - Vector2 v; - - if (dot > 0.9995f) { - v = v1.lerp(v2, p_c).normalized(); //linearly interpolate to avoid numerical precision issues - } else { - real_t angle = p_c * Math::acos(dot); - Vector2 v3 = (v2 - v1 * dot).normalized(); - v = v1 * Math::cos(angle) + v3 * Math::sin(angle); - } - - //construct matrix - Transform2D res(v.angle(), p1.lerp(p2, p_c)); - res.scale_basis(s1.lerp(s2, p_c)); - return res; +Transform2D Transform2D::interpolate_with(const Transform2D &p_transform, const real_t p_weight) const { + return Transform2D( + Math::lerp_angle(get_rotation(), p_transform.get_rotation(), p_weight), + get_scale().lerp(p_transform.get_scale(), p_weight), + Math::lerp_angle(get_skew(), p_transform.get_skew(), p_weight), + get_origin().lerp(p_transform.get_origin(), p_weight)); } void Transform2D::operator*=(const real_t p_val) { @@ -318,6 +297,18 @@ Transform2D Transform2D::operator*(const real_t p_val) const { return ret; } +void Transform2D::operator/=(const real_t p_val) { + columns[0] /= p_val; + columns[1] /= p_val; + columns[2] /= p_val; +} + +Transform2D Transform2D::operator/(const real_t p_val) const { + Transform2D ret(*this); + ret /= p_val; + return ret; +} + Transform2D::operator String() const { return "[X: " + columns[0].operator String() + ", Y: " + columns[1].operator String() + diff --git a/src/variant/transform3d.cpp b/src/variant/transform3d.cpp index d71e91911..19c9bea6e 100644 --- a/src/variant/transform3d.cpp +++ b/src/variant/transform3d.cpp @@ -78,20 +78,20 @@ void Transform3D::rotate_basis(const Vector3 &p_axis, real_t p_angle) { basis.rotate(p_axis, p_angle); } -Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up) const { +Transform3D Transform3D::looking_at(const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) const { #ifdef MATH_CHECKS ERR_FAIL_COND_V_MSG(origin.is_equal_approx(p_target), Transform3D(), "The transform's origin and target can't be equal."); #endif Transform3D t = *this; - t.basis = Basis::looking_at(p_target - origin, p_up); + t.basis = Basis::looking_at(p_target - origin, p_up, p_use_model_front); return t; } -void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up) { +void Transform3D::set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up, bool p_use_model_front) { #ifdef MATH_CHECKS ERR_FAIL_COND_MSG(p_eye.is_equal_approx(p_target), "The eye and target vectors can't be equal."); #endif - basis = Basis::looking_at(p_target - p_eye, p_up); + basis = Basis::looking_at(p_target - p_eye, p_up, p_use_model_front); origin = p_eye; } @@ -209,6 +209,17 @@ Transform3D Transform3D::operator*(const real_t p_val) const { return ret; } +void Transform3D::operator/=(const real_t p_val) { + basis /= p_val; + origin /= p_val; +} + +Transform3D Transform3D::operator/(const real_t p_val) const { + Transform3D ret(*this); + ret /= p_val; + return ret; +} + Transform3D::operator String() const { return "[X: " + basis.get_column(0).operator String() + ", Y: " + basis.get_column(1).operator String() + @@ -228,9 +239,9 @@ Transform3D::Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 & basis.set_column(2, p_z); } -Transform3D::Transform3D(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); +Transform3D::Transform3D(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_ox, real_t p_oy, real_t p_oz) { + basis = Basis(p_xx, p_xy, p_xz, p_yx, p_yy, p_yz, p_zx, p_zy, p_zz); + origin = Vector3(p_ox, p_oy, p_oz); } } // namespace godot diff --git a/src/variant/vector2.cpp b/src/variant/vector2.cpp index 12201f1fd..8ba4c8435 100644 --- a/src/variant/vector2.cpp +++ b/src/variant/vector2.cpp @@ -96,7 +96,7 @@ real_t Vector2::cross(const Vector2 &p_other) const { } Vector2 Vector2::sign() const { - return Vector2(SIGN(x), SIGN(y)); + return Vector2(Math::sign(x), Math::sign(y)); } Vector2 Vector2::floor() const { @@ -176,9 +176,9 @@ Vector2 Vector2::move_toward(const Vector2 &p_to, const real_t p_delta) const { // slide returns the component of the vector along the given plane, specified by its normal vector. Vector2 Vector2::slide(const Vector2 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized."); + ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 " + p_normal.operator String() + "must be normalized."); #endif - return *this - p_normal * this->dot(p_normal); + return *this - p_normal * dot(p_normal); } Vector2 Vector2::bounce(const Vector2 &p_normal) const { @@ -187,9 +187,9 @@ Vector2 Vector2::bounce(const Vector2 &p_normal) const { Vector2 Vector2::reflect(const Vector2 &p_normal) const { #ifdef MATH_CHECKS - ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 must be normalized."); + ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector2(), "The normal Vector2 " + p_normal.operator String() + "must be normalized."); #endif - return 2.0f * p_normal * this->dot(p_normal) - *this; + return 2.0f * p_normal * dot(p_normal) - *this; } bool Vector2::is_equal_approx(const Vector2 &p_v) const { diff --git a/src/variant/vector2i.cpp b/src/variant/vector2i.cpp index 4baff3bb3..91e128d3d 100644 --- a/src/variant/vector2i.cpp +++ b/src/variant/vector2i.cpp @@ -35,18 +35,6 @@ namespace godot { -Vector2i Vector2i::snapped(const Vector2i &p_step) const { - return Vector2i( - Math::snapped(x, p_step.x), - Math::snapped(y, p_step.y)); -} - -Vector2i Vector2i::snappedi(int32_t p_step) const { - return Vector2i( - Math::snapped(x, p_step), - Math::snapped(y, p_step)); -} - Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const { return Vector2i( CLAMP(x, p_min.x, p_max.x), @@ -59,20 +47,24 @@ Vector2i Vector2i::clampi(int32_t p_min, int32_t p_max) const { CLAMP(y, p_min, p_max)); } -int64_t Vector2i::length_squared() const { - return x * (int64_t)x + y * (int64_t)y; +Vector2i Vector2i::snapped(const Vector2i &p_step) const { + return Vector2i( + Math::snapped(x, p_step.x), + Math::snapped(y, p_step.y)); } -double Vector2i::length() const { - return Math::sqrt((double)length_squared()); +Vector2i Vector2i::snappedi(int32_t p_step) const { + return Vector2i( + Math::snapped(x, p_step), + Math::snapped(y, p_step)); } -int64_t Vector2i::distance_squared_to(const Vector2i &p_to) const { - return (p_to - *this).length_squared(); +int64_t Vector2i::length_squared() const { + return x * (int64_t)x + y * (int64_t)y; } -double Vector2i::distance_to(const Vector2i &p_to) const { - return (p_to - *this).length(); +double Vector2i::length() const { + return Math::sqrt((double)length_squared()); } Vector2i Vector2i::operator+(const Vector2i &p_v) const { @@ -97,39 +89,39 @@ Vector2i Vector2i::operator*(const Vector2i &p_v1) const { return Vector2i(x * p_v1.x, y * p_v1.y); } -Vector2i Vector2i::operator*(const int32_t &rvalue) const { - return Vector2i(x * rvalue, y * rvalue); +Vector2i Vector2i::operator*(const int32_t &p_rvalue) const { + return Vector2i(x * p_rvalue, y * p_rvalue); } -void Vector2i::operator*=(const int32_t &rvalue) { - x *= rvalue; - y *= rvalue; +void Vector2i::operator*=(const int32_t &p_rvalue) { + x *= p_rvalue; + y *= p_rvalue; } Vector2i Vector2i::operator/(const Vector2i &p_v1) const { return Vector2i(x / p_v1.x, y / p_v1.y); } -Vector2i Vector2i::operator/(const int32_t &rvalue) const { - return Vector2i(x / rvalue, y / rvalue); +Vector2i Vector2i::operator/(const int32_t &p_rvalue) const { + return Vector2i(x / p_rvalue, y / p_rvalue); } -void Vector2i::operator/=(const int32_t &rvalue) { - x /= rvalue; - y /= rvalue; +void Vector2i::operator/=(const int32_t &p_rvalue) { + x /= p_rvalue; + y /= p_rvalue; } Vector2i Vector2i::operator%(const Vector2i &p_v1) const { return Vector2i(x % p_v1.x, y % p_v1.y); } -Vector2i Vector2i::operator%(const int32_t &rvalue) const { - return Vector2i(x % rvalue, y % rvalue); +Vector2i Vector2i::operator%(const int32_t &p_rvalue) const { + return Vector2i(x % p_rvalue, y % p_rvalue); } -void Vector2i::operator%=(const int32_t &rvalue) { - x %= rvalue; - y %= rvalue; +void Vector2i::operator%=(const int32_t &p_rvalue) { + x %= p_rvalue; + y %= p_rvalue; } Vector2i Vector2i::operator-() const { diff --git a/src/variant/vector3.cpp b/src/variant/vector3.cpp index d2ad6a9fa..5297f4a93 100644 --- a/src/variant/vector3.cpp +++ b/src/variant/vector3.cpp @@ -61,25 +61,25 @@ Vector3 Vector3::clampf(real_t p_min, real_t p_max) const { CLAMP(z, p_min, p_max)); } -void Vector3::snap(const Vector3 p_step) { +void Vector3::snap(const Vector3 &p_step) { x = Math::snapped(x, p_step.x); y = Math::snapped(y, p_step.y); z = Math::snapped(z, p_step.z); } -void Vector3::snapf(real_t p_step) { - x = Math::snapped(x, p_step); - y = Math::snapped(y, p_step); - z = Math::snapped(z, p_step); -} - -Vector3 Vector3::snapped(const Vector3 p_step) const { +Vector3 Vector3::snapped(const Vector3 &p_step) const { Vector3 v = *this; v.snap(p_step); return v; } -Vector3 Vector3::snappedf(real_t p_step) const { +void Vector3::snapf(const real_t &p_step) { + x = Math::snapped(x, p_step); + y = Math::snapped(y, p_step); + z = Math::snapped(z, p_step); +} + +Vector3 Vector3::snappedf(const real_t &p_step) const { Vector3 v = *this; v.snapf(p_step); return v; @@ -122,23 +122,25 @@ Vector2 Vector3::octahedron_encode() const { Vector3 Vector3::octahedron_decode(const Vector2 &p_oct) { Vector2 f(p_oct.x * 2.0f - 1.0f, p_oct.y * 2.0f - 1.0f); Vector3 n(f.x, f.y, 1.0f - Math::abs(f.x) - Math::abs(f.y)); - float t = CLAMP(-n.z, 0.0f, 1.0f); + const real_t t = CLAMP(-n.z, 0.0f, 1.0f); n.x += n.x >= 0 ? -t : t; n.y += n.y >= 0 ? -t : t; return n.normalized(); } -Vector2 Vector3::octahedron_tangent_encode(const float sign) const { - Vector2 res = this->octahedron_encode(); +Vector2 Vector3::octahedron_tangent_encode(const float p_sign) const { + const real_t bias = 1.0f / (real_t)32767.0f; + Vector2 res = octahedron_encode(); + res.y = MAX(res.y, bias); res.y = res.y * 0.5f + 0.5f; - res.y = sign >= 0.0f ? res.y : 1 - res.y; + res.y = p_sign >= 0.0f ? res.y : 1 - res.y; return res; } -Vector3 Vector3::octahedron_tangent_decode(const Vector2 &p_oct, float *sign) { +Vector3 Vector3::octahedron_tangent_decode(const Vector2 &p_oct, float *r_sign) { Vector2 oct_compressed = p_oct; oct_compressed.y = oct_compressed.y * 2 - 1; - *sign = oct_compressed.y >= 0.0f ? 1.0f : -1.0f; + *r_sign = oct_compressed.y >= 0.0f ? 1.0f : -1.0f; oct_compressed.y = Math::abs(oct_compressed.y); Vector3 res = Vector3::octahedron_decode(oct_compressed); return res; diff --git a/src/variant/vector3i.cpp b/src/variant/vector3i.cpp index 7b25d8979..a18dde7db 100644 --- a/src/variant/vector3i.cpp +++ b/src/variant/vector3i.cpp @@ -35,20 +35,6 @@ namespace godot { -Vector3i Vector3i::snapped(const Vector3i &p_step) const { - return Vector3i( - Math::snapped(x, p_step.x), - Math::snapped(y, p_step.y), - Math::snapped(z, p_step.z)); -} - -Vector3i Vector3i::snappedi(int32_t p_step) const { - return Vector3i( - Math::snapped(x, p_step), - Math::snapped(y, p_step), - Math::snapped(z, p_step)); -} - Vector3i::Axis Vector3i::min_axis_index() const { return x < y ? (x < z ? Vector3i::AXIS_X : Vector3i::AXIS_Z) : (y < z ? Vector3i::AXIS_Y : Vector3i::AXIS_Z); } @@ -71,6 +57,20 @@ Vector3i Vector3i::clampi(int32_t p_min, int32_t p_max) const { CLAMP(z, p_min, p_max)); } +Vector3i Vector3i::snapped(const Vector3i &p_step) const { + return Vector3i( + Math::snapped(x, p_step.x), + Math::snapped(y, p_step.y), + Math::snapped(z, p_step.z)); +} + +Vector3i Vector3i::snappedi(const int32_t &p_step) const { + return Vector3i( + Math::snapped(x, p_step), + Math::snapped(y, p_step), + Math::snapped(z, p_step)); +} + Vector3i::operator String() const { return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ")"; } diff --git a/src/variant/vector4.cpp b/src/variant/vector4.cpp index 2f1bb5926..8312287a8 100644 --- a/src/variant/vector4.cpp +++ b/src/variant/vector4.cpp @@ -133,11 +133,12 @@ Vector4 Vector4::round() const { } Vector4 Vector4::lerp(const Vector4 &p_to, const real_t p_weight) const { - return Vector4( - x + (p_weight * (p_to.x - x)), - y + (p_weight * (p_to.y - y)), - z + (p_weight * (p_to.z - z)), - w + (p_weight * (p_to.w - w))); + Vector4 res = *this; + res.x = Math::lerp(res.x, p_to.x, p_weight); + res.y = Math::lerp(res.y, p_to.y, p_weight); + res.z = Math::lerp(res.z, p_to.z, p_weight); + res.w = Math::lerp(res.w, p_to.w, p_weight); + return res; } Vector4 Vector4::cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight) const { @@ -218,4 +219,8 @@ Vector4::operator String() const { static_assert(sizeof(Vector4) == 4 * sizeof(real_t)); +Vector4::operator Vector4i() const { + return Vector4i(x, y, z, w); +} + } // namespace godot diff --git a/src/variant/vector4i.cpp b/src/variant/vector4i.cpp index b0e330ca2..5c7b8ea8f 100644 --- a/src/variant/vector4i.cpp +++ b/src/variant/vector4i.cpp @@ -35,22 +35,6 @@ namespace godot { -Vector4i Vector4i::snapped(const Vector4i &p_step) const { - return Vector4i( - Math::snapped(x, p_step.x), - Math::snapped(y, p_step.y), - Math::snapped(z, p_step.z), - Math::snapped(w, p_step.w)); -} - -Vector4i Vector4i::snappedi(int32_t p_step) const { - return Vector4i( - Math::snapped(x, p_step), - Math::snapped(y, p_step), - Math::snapped(z, p_step), - Math::snapped(w, p_step)); -} - Vector4i::Axis Vector4i::min_axis_index() const { uint32_t min_index = 0; int32_t min_value = x; @@ -91,6 +75,22 @@ Vector4i Vector4i::clampi(int32_t p_min, int32_t p_max) const { CLAMP(w, p_min, p_max)); } +Vector4i Vector4i::snapped(const Vector4i &p_step) const { + return Vector4i( + Math::snapped(x, p_step.x), + Math::snapped(y, p_step.y), + Math::snapped(z, p_step.z), + Math::snapped(w, p_step.w)); +} + +Vector4i Vector4i::snappedi(const int32_t &p_step) const { + return Vector4i( + Math::snapped(x, p_step), + Math::snapped(y, p_step), + Math::snapped(z, p_step), + Math::snapped(w, p_step)); +} + Vector4i::operator String() const { return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ", " + itos(w) + ")"; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 42ea6e086..ab7397fa2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,143 +1,67 @@ -cmake_minimum_required(VERSION 3.13) -project(godot-cpp-test) - -set(GODOT_GDEXTENSION_DIR ../gdextension/ CACHE STRING "Path to GDExtension interface header directory") -set(CPP_BINDINGS_PATH ../ CACHE STRING "Path to C++ bindings") - -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - set(TARGET_PATH x11) -elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") - set(TARGET_PATH win64) -elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - set(TARGET_PATH macos) -else() - message(FATAL_ERROR "Not implemented support for ${CMAKE_SYSTEM_NAME}") -endif() - -# Change the output directory to the bin directory -set(BUILD_PATH ${CMAKE_SOURCE_DIR}/bin/${TARGET_PATH}) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${BUILD_PATH}") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BUILD_PATH}") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BUILD_PATH}") -SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${BUILD_PATH}") -SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${BUILD_PATH}") -SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BUILD_PATH}") -SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${BUILD_PATH}") -SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${BUILD_PATH}") -SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${BUILD_PATH}") - -# Set the c++ standard to c++17 -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - -set(GODOT_COMPILE_FLAGS ) -set(GODOT_LINKER_FLAGS ) - -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - # using Visual Studio C++ - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /WX") # /GF /MP - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /DTYPED_METHOD_BIND") - - if(CMAKE_BUILD_TYPE MATCHES Debug) - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MDd") # /Od /RTC1 /Zi - else() - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MD /O2") # /Oy /GL /Gy - STRING(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) - endif(CMAKE_BUILD_TYPE MATCHES Debug) - - # Disable conversion warning, truncation, unreferenced var, signed mismatch - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /wd4244 /wd4305 /wd4101 /wd4018 /wd4267") - - add_definitions(-DNOMINMAX) - - # Unkomment for warning level 4 - #if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") - # string(REGEX REPLACE "/W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - #endif() +# Testing Extension +# This is only linked to the template_release config. +# so it requires the template_release version of godot to run. + +add_library( godot-cpp-test SHARED EXCLUDE_FROM_ALL ) + +target_sources( godot-cpp-test + PRIVATE + src/example.cpp + src/example.h + src/register_types.cpp + src/register_types.h + src/tests.h +) -else() +set( TEST_TARGET "template_debug" CACHE STRING "Which godot-cpp::target to link against" ) +set_property( CACHE TEST_TARGET PROPERTY STRINGS "template_debug;template_release;editor" ) - set(GODOT_LINKER_FLAGS "-static-libgcc -static-libstdc++ -Wl,-R,'$$ORIGIN'") +target_link_libraries( godot-cpp-test + PRIVATE + godot-cpp::${TEST_TARGET} ) - set(GODOT_COMPILE_FLAGS "-fPIC -g -Wwrite-strings") +### Get useful properties of the library +get_target_property( GODOT_PLATFORM godot-cpp::${TEST_TARGET} GODOT_PLATFORM ) +get_target_property( GODOT_TARGET godot-cpp::${TEST_TARGET} GODOT_TARGET ) +get_target_property( GODOT_ARCH godot-cpp::${TEST_TARGET} GODOT_ARCH ) - if(CMAKE_BUILD_TYPE MATCHES Debug) - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0") - else() - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3") - endif(CMAKE_BUILD_TYPE MATCHES Debug) -endif() +set( OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/project/bin/" ) -# Disable exception handling. Godot doesn't use exceptions anywhere, and this -# saves around 20% of binary size and very significant build time (GH-80513). -option(GODOT_DISABLE_EXCEPTIONS ON "Force disabling exception handling code") -if (GODOT_DISABLE_EXCEPTIONS) - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0") - else() - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-exceptions") - endif() -else() - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc") - endif() -endif() +set_target_properties( godot-cpp-test + PROPERTIES + CXX_STANDARD 17 + CXX_EXTENSIONS OFF + CXX_VISIBILITY_PRESET ${GODOT_SYMBOL_VISIBILITY} -# Get Sources -file(GLOB_RECURSE SOURCES src/*.c**) -file(GLOB_RECURSE HEADERS include/*.h**) + POSITION_INDEPENDENT_CODE ON + BUILD_RPATH_USE_ORIGIN ON + LINK_SEARCH_START_STATIC ON + LINK_SEARCH_END_STATIC ON -# Define our godot-cpp library -add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS}) + # NOTE: Wrapping the output variables inside a generator expression + # prevents msvc generator from adding addition Config Directories + LIBRARY_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>" + RUNTIME_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>" + PDB_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>" #MSVC Only, ignored on other platforms -target_include_directories(${PROJECT_NAME} SYSTEM - PRIVATE - ${CPP_BINDINGS_PATH}/include - ${CPP_BINDINGS_PATH}/gen/include - ${GODOT_GDEXTENSION_DIR} + PREFIX "lib" + OUTPUT_NAME "gdexample.${GODOT_PLATFORM}.${GODOT_TARGET}.${GODOT_ARCH}" ) -# Create the correct name (godot.os.build_type.system_bits) -# Synchronized with godot-cpp's CMakeLists.txt - -set(BITS 32) -if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(BITS 64) -endif(CMAKE_SIZEOF_VOID_P EQUAL 8) - -if(CMAKE_BUILD_TYPE MATCHES Debug) - set(GODOT_CPP_BUILD_TYPE Debug) -else() - set(GODOT_CPP_BUILD_TYPE Release) -endif() - -string(TOLOWER ${CMAKE_SYSTEM_NAME} SYSTEM_NAME) -string(TOLOWER ${GODOT_CPP_BUILD_TYPE} BUILD_TYPE) - -if(ANDROID) - # Added the android abi after system name - set(SYSTEM_NAME ${SYSTEM_NAME}.${ANDROID_ABI}) -endif() +if( CMAKE_SYSTEM_NAME STREQUAL Darwin ) + get_target_property( OSX_ARCH godot-cpp::${TEST_TARGET} OSX_ARCHITECTURES ) -if(CMAKE_VERSION VERSION_GREATER "3.13") - target_link_directories(${PROJECT_NAME} - PRIVATE - ${CPP_BINDINGS_PATH}/bin/ - ) + set( OUTPUT_DIR "${OUTPUT_DIR}/libgdexample.macos.${TEST_TARGET}.framework") - target_link_libraries(${PROJECT_NAME} - godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}$<$>:.${BITS}> - ) -else() - target_link_libraries(${PROJECT_NAME} - ${CPP_BINDINGS_PATH}/bin/libgodot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}$<$>:.${BITS}>.a - ) -endif() + set_target_properties( godot-cpp-test + PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>" + RUNTIME_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>" -# Add the compile flags -set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS ${GODOT_COMPILE_FLAGS}) -set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY LINK_FLAGS ${GODOT_LINKER_FLAGS}) + OUTPUT_NAME "gdexample.macos.${TEST_TARGET}" + SUFFIX "" -set_property(TARGET ${PROJECT_NAME} PROPERTY OUTPUT_NAME "gdexample") + #macos options + OSX_ARCHITECTURES "${OSX_ARCH}" + ) +endif () diff --git a/test/run-tests.sh b/test/run-tests.sh index 728f6d4c3..775039672 100755 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -1,11 +1,11 @@ #!/bin/bash -GODOT=${GODOT:-godot} +BLAZIUM=${BLAZIUM:-blazium} END_STRING="==== TESTS FINISHED ====" FAILURE_STRING="******** FAILED ********" -OUTPUT=$($GODOT --path project --debug --headless --quit) +OUTPUT=$($BLAZIUM --path project --debug --headless --quit) ERRCODE=$? echo "$OUTPUT" diff --git a/tools/android.py b/tools/android.py index 0222121eb..fee4ed255 100644 --- a/tools/android.py +++ b/tools/android.py @@ -120,4 +120,9 @@ def generate(env): env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED"]) + # Refer to https://github.com/godotengine/godot/blob/master/platform/android/detect.py + # LTO benefits for Android (size, performance) haven't been clearly established yet. + if env["lto"] == "auto": + env["lto"] = "none" + common_compiler_flags.generate(env) diff --git a/tools/common_compiler_flags.py b/tools/common_compiler_flags.py index 6a1fb6931..e645f390f 100644 --- a/tools/common_compiler_flags.py +++ b/tools/common_compiler_flags.py @@ -22,6 +22,10 @@ def exists(env): def generate(env): + assert env["lto"] in ["thin", "full", "none"], "Unrecognized lto: {}".format(env["lto"]) + if env["lto"] != "none": + print("Using LTO: " + env["lto"]) + # Require C++17 if env.get("is_msvc", False): env.Append(CXXFLAGS=["/std:c++17"]) @@ -64,6 +68,22 @@ def generate(env): env.Append(LINKFLAGS=["/OPT:REF"]) elif env["optimize"] == "debug" or env["optimize"] == "none": env.Append(CCFLAGS=["/Od"]) + + if env["lto"] == "thin": + if not env["use_llvm"]: + print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.") + env.Exit(255) + + env.Append(CCFLAGS=["-flto=thin"]) + env.Append(LINKFLAGS=["-flto=thin"]) + elif env["lto"] == "full": + if env["use_llvm"]: + env.Append(CCFLAGS=["-flto"]) + env.Append(LINKFLAGS=["-flto"]) + else: + env.AppendUnique(CCFLAGS=["/GL"]) + env.AppendUnique(ARFLAGS=["/LTCG"]) + env.AppendUnique(LINKFLAGS=["/LTCG"]) else: if env["debug_symbols"]: # Adding dwarf-4 explicitly makes stacktraces work with clang builds, @@ -91,3 +111,13 @@ def generate(env): env.Append(CCFLAGS=["-Og"]) elif env["optimize"] == "none": env.Append(CCFLAGS=["-O0"]) + + if env["lto"] == "thin": + if (env["platform"] == "windows" or env["platform"] == "linux") and not env["use_llvm"]: + print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.") + env.Exit(255) + env.Append(CCFLAGS=["-flto=thin"]) + env.Append(LINKFLAGS=["-flto=thin"]) + elif env["lto"] == "full": + env.Append(CCFLAGS=["-flto"]) + env.Append(LINKFLAGS=["-flto"]) diff --git a/tools/godotcpp.py b/tools/godotcpp.py index b2a63dc1e..77a0740fc 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -326,6 +326,14 @@ def options(opts, env): ("none", "custom", "debug", "speed", "speed_trace", "size"), ) ) + opts.Add( + EnumVariable( + "lto", + "Link-time optimization", + "none", + ("none", "auto", "thin", "full"), + ) + ) opts.Add(BoolVariable("debug_symbols", "Build with debugging symbols", True)) opts.Add(BoolVariable("dev_build", "Developer build with dev-only debugging code (DEV_ENABLED)", False)) opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False)) diff --git a/tools/ios.py b/tools/ios.py index 9675ab1ac..25c17db31 100644 --- a/tools/ios.py +++ b/tools/ios.py @@ -97,4 +97,9 @@ def generate(env): env.Append(CPPDEFINES=["IOS_ENABLED", "UNIX_ENABLED"]) + # Refer to https://github.com/godotengine/godot/blob/master/platform/ios/detect.py: + # Disable by default as it makes linking in Xcode very slow. + if env["lto"] == "auto": + env["lto"] = "none" + common_compiler_flags.generate(env) diff --git a/tools/linux.py b/tools/linux.py index 0b2687880..9e85d8803 100644 --- a/tools/linux.py +++ b/tools/linux.py @@ -39,4 +39,8 @@ def generate(env): env.Append(CPPDEFINES=["LINUX_ENABLED", "UNIX_ENABLED"]) + # Refer to https://github.com/godotengine/godot/blob/master/platform/linuxbsd/detect.py + if env["lto"] == "auto": + env["lto"] = "full" + common_compiler_flags.generate(env) diff --git a/tools/macos.py b/tools/macos.py index 741815051..f88e47ff1 100644 --- a/tools/macos.py +++ b/tools/macos.py @@ -73,4 +73,9 @@ def generate(env): env.Append(CPPDEFINES=["MACOS_ENABLED", "UNIX_ENABLED"]) + # Refer to https://github.com/godotengine/godot/blob/master/platform/macos/detect.py + # LTO benefits for macOS (size, performance) haven't been clearly established yet. + if env["lto"] == "auto": + env["lto"] = "none" + common_compiler_flags.generate(env) diff --git a/tools/web.py b/tools/web.py index e878a78f3..f1a441869 100644 --- a/tools/web.py +++ b/tools/web.py @@ -52,4 +52,8 @@ def generate(env): env.Append(CPPDEFINES=["WEB_ENABLED", "UNIX_ENABLED"]) + # Refer to https://github.com/godotengine/godot/blob/master/platform/web/detect.py + if env["lto"] == "auto": + env["lto"] = "full" + common_compiler_flags.generate(env) diff --git a/tools/windows.py b/tools/windows.py index 2e8d609ea..f66bce423 100644 --- a/tools/windows.py +++ b/tools/windows.py @@ -78,6 +78,7 @@ def options(opts): opts.Add(BoolVariable("use_mingw", "Use the MinGW compiler instead of MSVC - only effective on Windows", False)) opts.Add(BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True)) opts.Add(BoolVariable("silence_msvc", "Silence MSVC's cl/link stdout bloat, redirecting errors to stderr.", True)) + opts.Add(BoolVariable("debug_crt", "Compile with MSVC's debug CRT (/MDd)", False)) opts.Add(BoolVariable("use_llvm", "Use the LLVM compiler (MVSC or MinGW depending on the use_mingw flag)", False)) opts.Add("mingw_prefix", "MinGW prefix", mingw) @@ -117,10 +118,14 @@ def generate(env): env["CC"] = "clang-cl" env["CXX"] = "clang-cl" - if env["use_static_cpp"]: - env.Append(CCFLAGS=["/MT"]) + if env["debug_crt"]: + # Always use dynamic runtime, static debug CRT breaks thread_local. + env.AppendUnique(CCFLAGS=["/MDd"]) else: - env.Append(CCFLAGS=["/MD"]) + if env["use_static_cpp"]: + env.AppendUnique(CCFLAGS=["/MT"]) + else: + env.AppendUnique(CCFLAGS=["/MD"]) if env["silence_msvc"] and not env.GetOption("clean"): silence_msvc(env) @@ -198,4 +203,12 @@ def generate(env): env.Append(CPPDEFINES=["WINDOWS_ENABLED"]) + # Refer to https://github.com/godotengine/godot/blob/master/platform/windows/detect.py + if env["lto"] == "auto": + if env.get("is_msvc", False): + # No LTO by default for MSVC, doesn't help. + env["lto"] = "none" + else: # Release + env["lto"] = "full" + common_compiler_flags.generate(env)