├── .gdignore ├── .gitmodules ├── test ├── project │ ├── main.gd.uid │ ├── example.gd.uid │ ├── test_base.gd.uid │ ├── example.gdextension.uid │ ├── icon.png │ ├── example.gd │ ├── default_env.tres │ ├── project.godot │ ├── icon.png.import │ ├── bin │ │ ├── libgdexample.macos.template_debug.framework │ │ │ └── Resources │ │ │ │ └── Info.plist │ │ └── libgdexample.macos.template_release.framework │ │ │ └── Resources │ │ │ └── Info.plist │ ├── main.tscn │ ├── test_base.gd │ └── example.gdextension ├── build_profile.json ├── src │ ├── register_types.h │ ├── tests.h │ └── register_types.cpp ├── run-tests.sh ├── generate_xcframework.sh ├── .gitignore ├── doc_classes │ └── Example.xml ├── README.md ├── SConstruct └── CMakeLists.txt ├── .gitattributes ├── .github ├── dependabot.yml ├── CODEOWNERS ├── actions │ ├── godot-cache-save │ │ └── action.yml │ ├── godot-cache-restore │ │ └── action.yml │ └── setup-godot-cpp │ │ └── action.yml ├── ISSUE_TEMPLATE │ ├── config.yml │ └── bug_report.yml └── workflows │ ├── static_checks.yml │ └── runner.yml ├── .editorconfig ├── misc ├── ci │ └── sources.list └── scripts │ ├── file_format.py │ ├── check_get_file_list.py │ ├── make_tarball.sh │ ├── check_ci_log.py │ ├── header_guards.py │ └── copyright_headers.py ├── .git-blame-ignore-revs ├── gdextension └── README.md ├── Makefile ├── pyproject.toml ├── LICENSE.md ├── cmake ├── web.cmake ├── ios.cmake ├── linux.cmake ├── macos.cmake ├── android.cmake ├── emsdkHack.cmake └── windows.cmake ├── SConstruct ├── tools ├── my_spawn.py ├── linux.py ├── web.py ├── macos.py ├── ios.py ├── android.py └── common_compiler_flags.py ├── doc_source_generator.py ├── .pre-commit-config.yaml ├── src ├── core │ ├── print_string.cpp │ ├── method_bind.cpp │ ├── memory.cpp │ ├── error_macros.cpp │ └── object.cpp ├── variant │ ├── rect2i.cpp │ ├── variant_internal.cpp │ ├── vector3i.cpp │ ├── vector4i.cpp │ └── vector2i.cpp └── classes │ ├── editor_plugin_registration.cpp │ └── low_level.cpp ├── CMakeLists.txt ├── include └── godot_cpp │ ├── templates │ ├── spin_lock.hpp │ ├── search_array.hpp │ ├── pair.hpp │ └── vset.hpp │ ├── core │ ├── math.compat.inc │ ├── mutex_lock.hpp │ ├── object_id.hpp │ ├── print_string.hpp │ ├── math_defs.hpp │ ├── builtin_ptrcall.hpp │ ├── engine_ptrcall.hpp │ └── property_info.hpp │ ├── variant │ ├── array_helpers.hpp │ ├── callable_custom.hpp │ └── char_string.hpp │ └── classes │ └── editor_plugin_registration.hpp └── .gitignore /.gdignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/project/main.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bujp6xsb8pfqk 2 | -------------------------------------------------------------------------------- /test/project/example.gd.uid: -------------------------------------------------------------------------------- 1 | uid://1htvqeulgew6 2 | -------------------------------------------------------------------------------- /test/project/test_base.gd.uid: -------------------------------------------------------------------------------- 1 | uid://dwbwwljpx3cp 2 | -------------------------------------------------------------------------------- /test/project/example.gdextension.uid: -------------------------------------------------------------------------------- 1 | uid://dhm7q8lygqyol 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Normalize EOL for all files that Git considers text files 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /test/project/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Redot-Engine/redot-cpp/HEAD/test/project/icon.png -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | -------------------------------------------------------------------------------- /test/project/example.gd: -------------------------------------------------------------------------------- 1 | extends Example 2 | 3 | func _do_something_virtual(p_name, p_value): 4 | custom_signal.emit(p_name, p_value) 5 | return "Implemented" 6 | -------------------------------------------------------------------------------- /test/project/default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=3 uid="uid://dtd3q2x2ulcsi"] 2 | 3 | [sub_resource type="Sky" id="1"] 4 | 5 | [resource] 6 | background_mode = 2 7 | sky = SubResource("1") 8 | -------------------------------------------------------------------------------- /test/build_profile.json: -------------------------------------------------------------------------------- 1 | { 2 | "enabled_classes": [ 3 | "Control", 4 | "InputEventKey", 5 | "Label", 6 | "MultiplayerAPI", 7 | "MultiplayerPeer", 8 | "OS", 9 | "TileMap", 10 | "TileSet", 11 | "Viewport" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Lines starting with '#' are comments. 2 | # Each line is a file pattern followed by one or more owners. 3 | # Owners can be @users, @org/teams or emails 4 | 5 | * @godotengine/gdextension 6 | .github/ @godotengine/buildsystem 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = tab 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [{*.py,SConstruct}] 12 | indent_style = space 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | indent_style = space 17 | -------------------------------------------------------------------------------- /misc/ci/sources.list: -------------------------------------------------------------------------------- 1 | deb http://archive.ubuntu.com/ubuntu/ focal main restricted universe multiverse 2 | deb http://archive.ubuntu.com/ubuntu/ focal-updates main restricted universe multiverse 3 | deb http://archive.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse 4 | deb http://archive.ubuntu.com/ubuntu/ focal-backports main restricted universe multiverse 5 | -------------------------------------------------------------------------------- /test/src/register_types.h: -------------------------------------------------------------------------------- 1 | /* godot-cpp integration testing project. 2 | * 3 | * This is free and unencumbered software released into the public domain. 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | using namespace godot; 11 | 12 | void initialize_example_module(ModuleInitializationLevel p_level); 13 | void uninitialize_example_module(ModuleInitializationLevel p_level); 14 | -------------------------------------------------------------------------------- /test/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | REDOT=${REDOT:-redot} 4 | 5 | END_STRING="==== TESTS FINISHED ====" 6 | FAILURE_STRING="******** FAILED ********" 7 | 8 | OUTPUT=$($REDOT --path project --debug --headless --quit) 9 | ERRCODE=$? 10 | 11 | echo "$OUTPUT" 12 | echo 13 | 14 | if ! echo "$OUTPUT" | grep -e "$END_STRING" >/dev/null; then 15 | echo "ERROR: Tests failed to complete" 16 | exit 1 17 | fi 18 | 19 | if echo "$OUTPUT" | grep -e "$FAILURE_STRING" >/dev/null; then 20 | exit 1 21 | fi 22 | 23 | # Success! 24 | exit 0 25 | -------------------------------------------------------------------------------- /test/generate_xcframework.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | scons arch=universal ios_simulator=yes platform=ios target=$1 $2 4 | scons arch=arm64 ios_simulator=no platform=ios target=$1 $2 5 | 6 | xcodebuild -create-xcframework -library ./project/bin/libgdexample.ios.$1.a -library ./project/bin/libgdexample.ios.$1.simulator.a -output ./project/bin/libgdexample.ios.$1.xcframework 7 | xcodebuild -create-xcframework -library ../bin/libredot-cpp.ios.$1.arm64.a -library ../bin/libredot-cpp.ios.$1.universal.simulator.a -output ./project/bin/libredot-cpp.ios.$1.xcframework 8 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated directories with binaries 2 | build 3 | bin 4 | 5 | # Godot 4+ specific ignores 6 | .godot/ 7 | 8 | # Godot-specific ignores 9 | .import/ 10 | export.cfg 11 | export_presets.cfg 12 | # Dummy HTML5 export presets file for continuous integration 13 | !.github/dist/export_presets.cfg 14 | 15 | # Imported translations (automatically generated from CSV files) 16 | *.translation 17 | 18 | # Mono-specific ignores 19 | .mono/ 20 | data_*/ 21 | mono_crash.*.json 22 | 23 | # System/tool-specific ignores 24 | .directory 25 | *~ 26 | -------------------------------------------------------------------------------- /.github/actions/godot-cache-save/action.yml: -------------------------------------------------------------------------------- 1 | name: Save Godot build cache 2 | description: Save Godot build cache. 3 | inputs: 4 | cache-name: 5 | description: The cache base name (job name by default). 6 | default: ${{ github.job }} 7 | scons-cache: 8 | description: The SCons cache path. 9 | default: ${{ github.workspace }}/.scons-cache/ 10 | 11 | runs: 12 | using: composite 13 | steps: 14 | - name: Save SCons cache directory 15 | uses: actions/cache/save@v4 16 | with: 17 | path: ${{ inputs.scons-cache }} 18 | key: ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }} 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | 3 | contact_links: 4 | - name: Redot proposals 5 | url: https://github.com/Redot-Engine/redot-proposals 6 | about: Please submit feature proposals on the Redot proposals repository, not here. 7 | 8 | - name: Redot documentation repository 9 | url: https://github.com/Redot-Engine/redot-docs 10 | about: Please report issues with documentation on the Redot documentation repository, not here. 11 | 12 | - name: Redot community channels 13 | url: https://Redot-Engine.org/community 14 | about: Please ask for technical support on one of the other community channels, not here. 15 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # This file contains a list of Git commit hashes that should be hidden from the 2 | # regular Git history. Typically, this includes commits involving mass auto-formatting 3 | # or other normalizations. Commit hashes *must* use the full 40-character notation. 4 | # To apply the ignore list in your local Git client, you must run: 5 | # 6 | # git config blame.ignoreRevsFile .git-blame-ignore-revs 7 | # 8 | # This file is automatically used by GitHub.com's blame view. 9 | 10 | # Rebrand preambles to Redot 11 | d3bd3484fc9baad20a7cc4c9371a5f4dd70744cd 12 | 13 | # Style: Replace header guards with `#pragma once` 14 | 7056c996dd43ae1aa466c94d95cc2fe63853d8a9 15 | -------------------------------------------------------------------------------- /test/project/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="GDExtension Test Project" 14 | run/main_scene="res://main.tscn" 15 | config/features=PackedStringArray("4.4") 16 | config/icon="res://icon.png" 17 | 18 | [native_extensions] 19 | 20 | paths=["res://example.gdextension"] 21 | 22 | [rendering] 23 | 24 | textures/vram_compression/import_etc2_astc=true 25 | environment/defaults/default_environment="res://default_env.tres" 26 | -------------------------------------------------------------------------------- /test/doc_classes/Example.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A test control defined in GDExtension. 5 | 6 | 7 | A control used for the automated GDExtension tests. 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Tests a simple function call. 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /gdextension/README.md: -------------------------------------------------------------------------------- 1 | # GDExtension header and API 2 | 3 | This repository contains the C header and API JSON for 4 | [**Redot Engine**](https://github.com/Redot-Engine/redot-engine)'s *GDExtensions* API. 5 | 6 | ## Updating header and API 7 | 8 | If the current branch is not up-to-date for your needs, or if you want to sync 9 | the header and API JSON with your own modified version of Redot, here is the 10 | update procedure used to sync this repository with upstream releases: 11 | 12 | - Compile [Redot Engine](https://github.com/Redot-Engine/redot-engine) at the specific 13 | version/commit which you are using. 14 | * Or if you use an official release, download that version of the Redot editor. 15 | - Use the compiled or downloaded executable to generate the `extension_api.json` 16 | and `gdextension_interface.h` files with: 17 | 18 | ``` 19 | redot --dump-extension-api --dump-gdextension-interface 20 | ``` 21 | -------------------------------------------------------------------------------- /test/project/icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cswr8vy4lt7dt" 6 | path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.png" 14 | dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /.github/workflows/static_checks.yml: -------------------------------------------------------------------------------- 1 | name: 📊 Static Checks 2 | on: 3 | workflow_call: 4 | 5 | concurrency: 6 | group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-static 7 | cancel-in-progress: true 8 | 9 | jobs: 10 | static-checks: 11 | name: Format (clang-format, ruff format, file format) 12 | runs-on: ubuntu-22.04 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 2 18 | 19 | - name: Get changed files 20 | id: changed-files 21 | uses: tj-actions/changed-files@v45 22 | 23 | - name: Style checks via pre-commit 24 | uses: pre-commit/action@v3.0.1 25 | with: 26 | extra_args: --verbose --hook-stage manual --files ${{ steps.changed-files.outputs.all_changed_files }} 27 | 28 | - name: Check generated files consistency 29 | run: 30 | python misc/scripts/check_get_file_list.py 31 | -------------------------------------------------------------------------------- /test/project/bin/libgdexample.macos.template_debug.framework/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleExecutable 6 | libgdexample.template_debug 7 | CFBundleIdentifier 8 | org.godotengine.libgdexample 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | libgdexample.macos.template_debug 13 | CFBundlePackageType 14 | FMWK 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleSupportedPlatforms 18 | 19 | MacOSX 20 | 21 | CFBundleVersion 22 | 1.0.0 23 | LSMinimumSystemVersion 24 | 10.12 25 | 26 | 27 | -------------------------------------------------------------------------------- /test/project/bin/libgdexample.macos.template_release.framework/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleExecutable 6 | libgdexample.template_release 7 | CFBundleIdentifier 8 | org.godotengine.libgdexample 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | libgdexample.macos.template_release 13 | CFBundlePackageType 14 | FMWK 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleSupportedPlatforms 18 | 19 | MacOSX 20 | 21 | CFBundleVersion 22 | 1.0.0 23 | LSMinimumSystemVersion 24 | 10.12 25 | 26 | 27 | -------------------------------------------------------------------------------- /test/project/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://dmx2xuigcpvt4"] 2 | 3 | [ext_resource type="Script" uid="uid://bujp6xsb8pfqk" path="res://main.gd" id="1_qesh5"] 4 | [ext_resource type="Script" uid="uid://1htvqeulgew6" path="res://example.gd" id="2_jju25"] 5 | 6 | [node name="Node" type="Node"] 7 | script = ExtResource("1_qesh5") 8 | 9 | [node name="Example" type="Example" parent="."] 10 | script = ExtResource("2_jju25") 11 | 12 | [node name="ExampleMin" type="ExampleMin" parent="Example"] 13 | layout_mode = 0 14 | 15 | [node name="Label" type="Label" parent="Example"] 16 | layout_mode = 0 17 | offset_left = 194.0 18 | offset_top = -2.0 19 | offset_right = 234.0 20 | offset_bottom = 21.0 21 | 22 | [node name="Button" type="Button" parent="."] 23 | offset_right = 79.0 24 | offset_bottom = 29.0 25 | text = "Click me!" 26 | 27 | [node name="ExampleChild" type="ExampleChild" parent="."] 28 | 29 | [connection signal="custom_signal" from="Example" to="." method="_on_Example_custom_signal"] 30 | -------------------------------------------------------------------------------- /.github/actions/godot-cache-restore/action.yml: -------------------------------------------------------------------------------- 1 | name: Restore Godot build cache 2 | description: Restore Godot build cache. 3 | inputs: 4 | cache-name: 5 | description: The cache base name (job name by default). 6 | default: ${{ github.job }} 7 | scons-cache: 8 | description: The SCons cache path. 9 | default: ${{ github.workspace }}/.scons-cache/ 10 | 11 | runs: 12 | using: composite 13 | steps: 14 | - name: Restore SCons cache directory 15 | uses: actions/cache/restore@v4 16 | with: 17 | path: ${{ inputs.scons-cache }} 18 | key: ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }} 19 | 20 | restore-keys: | 21 | ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }} 22 | ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }} 23 | ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-refs/heads/${{ env.GODOT_BASE_BRANCH }} 24 | ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }} 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARGET = template_debug 2 | 3 | BASE = scons target=$(TARGET) $(EXTRA_ARGS) 4 | LINUX = $(BASE) platform=linux 5 | WINDOWS = $(BASE) platform=windows 6 | MACOS = $(BASE) platform=macos 7 | 8 | 9 | .PHONY: usage 10 | usage: 11 | @echo -e "Specify one of the available targets:\n" 12 | # https://stackoverflow.com/a/26339924 13 | @LC_ALL=C $(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/(^|\n)# Files(\n|$$)/,/(^|\n)# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | grep -E -v -e '^[^[:alnum:]]' -e '^$@$$' 14 | @echo -e "\nDefine the SCons target with TARGET, and pass extra SCons arguments with EXTRA_ARGS." 15 | 16 | 17 | linux: 18 | make linux32 19 | make linux64 20 | 21 | linux32: SConstruct 22 | $(LINUX) arch=x86_32 23 | 24 | linux64: SConstruct 25 | $(LINUX) arch=x86_64 26 | 27 | 28 | windows: 29 | make windows32 30 | make windows64 31 | 32 | windows32: SConstruct 33 | $(WINDOWS) arch=x86_32 34 | 35 | windows64: SConstruct 36 | $(WINDOWS) arch=x86_64 37 | 38 | 39 | macos: SConstruct 40 | $(MACOS) 41 | -------------------------------------------------------------------------------- /test/src/tests.h: -------------------------------------------------------------------------------- 1 | /* godot-cpp integration testing project. 2 | * 3 | * This is free and unencumbered software released into the public domain. 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.mypy] 2 | disallow_any_generics = true 3 | explicit_package_bases = true 4 | ignore_missing_imports = true 5 | namespace_packages = true 6 | no_implicit_optional = true 7 | pretty = true 8 | scripts_are_modules = true 9 | show_column_numbers = true 10 | warn_redundant_casts = true 11 | warn_return_any = true 12 | warn_unreachable = true 13 | 14 | [tool.ruff] 15 | extend-include = ["SConstruct"] 16 | line-length = 120 17 | target-version = "py37" 18 | 19 | [tool.ruff.lint] 20 | extend-select = [ 21 | "I", # isort 22 | ] 23 | 24 | [tool.ruff.lint.per-file-ignores] 25 | "SConstruct" = [ 26 | "F821", # Undefined name 27 | ] 28 | 29 | [tool.codespell] 30 | enable-colors = "" 31 | write-changes = "" 32 | check-hidden = "" 33 | quiet-level = 3 34 | builtin = "clear,rare,en-GB_to_en-US" 35 | ignore-words-list = """\ 36 | breaked, 37 | cancelled, 38 | checkin, 39 | curvelinear, 40 | doubleclick, 41 | expct, 42 | findn, 43 | gird, 44 | hel, 45 | inout, 46 | labelin, 47 | lod, 48 | mis, 49 | nd, 50 | numer, 51 | ot, 52 | outin, 53 | requestor, 54 | te, 55 | textin, 56 | thirdparty, 57 | vai 58 | """ 59 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2024-present Redot Engine contributors 4 | Copyright (c) 2017-present Godot Engine contributors. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /cmake/web.cmake: -------------------------------------------------------------------------------- 1 | #[=======================================================================[.rst: 2 | Web 3 | --- 4 | 5 | This file contains functions for options and configuration for targeting the 6 | Web platform 7 | 8 | ]=======================================================================] 9 | 10 | # Emscripten requires this hack for use of the SHARED option 11 | set(CMAKE_PROJECT_godot-cpp_INCLUDE cmake/emsdkHack.cmake) 12 | 13 | #[==============================[ Web Options ]==============================] 14 | function(web_options) 15 | endfunction() 16 | 17 | #[===========================[ Target Generation ]===========================] 18 | function(web_generate) 19 | target_compile_definitions(godot-cpp PUBLIC WEB_ENABLED UNIX_ENABLED) 20 | 21 | target_compile_options( 22 | godot-cpp 23 | PUBLIC # 24 | -sSIDE_MODULE 25 | -sSUPPORT_LONGJMP=wasm 26 | $<${THREADS_ENABLED}:-sUSE_PTHREADS=1> 27 | ) 28 | 29 | target_link_options( 30 | godot-cpp 31 | INTERFACE # 32 | -sWASM_BIGINT 33 | -sSUPPORT_LONGJMP=wasm 34 | -fvisibility=hidden 35 | -shared 36 | ) 37 | 38 | common_compiler_flags() 39 | endfunction() 40 | -------------------------------------------------------------------------------- /cmake/ios.cmake: -------------------------------------------------------------------------------- 1 | #[=======================================================================[.rst: 2 | iOS 3 | --- 4 | 5 | This file contains functions for options and configuration for targeting the 6 | iOS platform 7 | 8 | ]=======================================================================] 9 | 10 | #[==============================[ iOS Options ]==============================] 11 | function(ios_options) 12 | #[[ Options from SCons 13 | 14 | TODO ios_simulator: Target iOS Simulator 15 | Default: False 16 | 17 | TODO ios_min_version: Target minimum iphoneos/iphonesimulator version 18 | Default: 12.0 19 | 20 | TODO IOS_TOOLCHAIN_PATH: Path to iOS toolchain 21 | Default: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain", 22 | 23 | TODO IOS_SDK_PATH: Path to the iOS SDK 24 | Default: '' 25 | 26 | TODO ios_triple: Triple for ios toolchain 27 | Default: if has_ios_osxcross(): 'ios_triple' else '' 28 | ]] 29 | endfunction() 30 | 31 | #[===========================[ Target Generation ]===========================] 32 | function(ios_generate) 33 | target_compile_definitions(godot-cpp PUBLIC IOS_ENABLED UNIX_ENABLED) 34 | 35 | common_compiler_flags() 36 | endfunction() 37 | -------------------------------------------------------------------------------- /misc/scripts/file_format.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | 6 | if len(sys.argv) < 2: 7 | print("Invalid usage of file_format.py, it should be called with a path to one or multiple files.") 8 | sys.exit(1) 9 | 10 | BOM = b"\xef\xbb\xbf" 11 | 12 | changed = [] 13 | invalid = [] 14 | 15 | for file in sys.argv[1:]: 16 | try: 17 | with open(file, "rt", encoding="utf-8") as f: 18 | original = f.read() 19 | except UnicodeDecodeError: 20 | invalid.append(file) 21 | continue 22 | 23 | if original == "": 24 | continue 25 | 26 | revamp = "\n".join([line.rstrip("\n\r\t ") for line in original.splitlines(True)]).rstrip("\n") + "\n" 27 | 28 | new_raw = revamp.encode(encoding="utf-8") 29 | if new_raw.startswith(BOM): 30 | new_raw = new_raw[len(BOM) :] 31 | 32 | with open(file, "rb") as f: 33 | old_raw = f.read() 34 | 35 | if old_raw != new_raw: 36 | changed.append(file) 37 | with open(file, "wb") as f: 38 | f.write(new_raw) 39 | 40 | if changed: 41 | for file in changed: 42 | print(f"FIXED: {file}") 43 | if invalid: 44 | for file in invalid: 45 | print(f"REQUIRES MANUAL CHANGES: {file}") 46 | sys.exit(1) 47 | -------------------------------------------------------------------------------- /cmake/linux.cmake: -------------------------------------------------------------------------------- 1 | #[=======================================================================[.rst: 2 | Linux 3 | ----- 4 | 5 | This file contains functions for options and configuration for targeting the 6 | Linux platform 7 | 8 | ]=======================================================================] 9 | 10 | #[=============================[ Linux Options ]=============================] 11 | function(linux_options) 12 | #[[ Options from SCons 13 | use_llvm : Use the LLVM compiler 14 | Not implemented as compiler selection is managed by CMake. Look to 15 | doc/cmake.rst for examples. 16 | ]] 17 | option(GODOTCPP_USE_STATIC_CPP "Link libgcc and libstdc++ statically for better portability" ON) 18 | endfunction() 19 | 20 | #[===========================[ Target Generation ]===========================] 21 | function(linux_generate) 22 | set(STATIC_CPP "$") 23 | 24 | target_compile_definitions(godot-cpp PUBLIC LINUX_ENABLED UNIX_ENABLED) 25 | 26 | # gersemi: off 27 | target_link_options( 28 | godot-cpp 29 | PUBLIC 30 | $<${STATIC_CPP}: 31 | -static-libgcc 32 | -static-libstdc++ 33 | > 34 | ) 35 | # gersemi: on 36 | 37 | common_compiler_flags() 38 | endfunction() 39 | -------------------------------------------------------------------------------- /cmake/macos.cmake: -------------------------------------------------------------------------------- 1 | #[=======================================================================[.rst: 2 | MacOS 3 | ----- 4 | 5 | This file contains functions for options and configuration for targeting the 6 | MacOS platform 7 | 8 | Universal Builds 9 | ---------------- 10 | 11 | To build universal binaries, ie targeting both x86_64 and arm64, use 12 | the CMAKE_OSX_ARCHITECTURES variable prior to any project calls. 13 | https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_ARCHITECTURES.html 14 | 15 | ]=======================================================================] 16 | 17 | # Find Requirements 18 | if(APPLE) 19 | set(CMAKE_OSX_SYSROOT $ENV{SDKROOT}) 20 | endif(APPLE) 21 | 22 | #[=============================[ MacOS Options ]=============================] 23 | function(macos_options) 24 | #[[ Options from SCons 25 | TODO macos_deployment_target: macOS deployment target 26 | Default: 'default' 27 | 28 | TODO macos_sdk_path: macOS SDK path 29 | Default: '' 30 | 31 | TODO osxcross_sdk: OSXCross SDK version 32 | Default: if has_osxcross(): "darwin16" else None 33 | ]] 34 | endfunction() 35 | 36 | #[===========================[ Target Generation ]===========================] 37 | function(macos_generate) 38 | target_compile_definitions(godot-cpp PUBLIC MACOS_ENABLED UNIX_ENABLED) 39 | 40 | common_compiler_flags() 41 | endfunction() 42 | -------------------------------------------------------------------------------- /misc/scripts/check_get_file_list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | from pathlib import Path 6 | 7 | sys.path.insert(1, os.path.join(os.path.dirname(__file__), "..", "..")) 8 | 9 | from binding_generator import _generate_bindings, _get_file_list 10 | from build_profile import generate_trimmed_api 11 | 12 | api_filepath = "gdextension/extension_api.json" 13 | bits = "64" 14 | precision = "single" 15 | output_dir = "self_test" 16 | 17 | 18 | def test(profile_filepath=""): 19 | api = generate_trimmed_api(api_filepath, profile_filepath) 20 | _generate_bindings( 21 | api, 22 | api_filepath, 23 | use_template_get_node=False, 24 | bits=bits, 25 | precision=precision, 26 | output_dir=output_dir, 27 | ) 28 | flist = _get_file_list(api, output_dir, headers=True, sources=True) 29 | 30 | p = Path(output_dir) / "gen" 31 | allfiles = [str(f.as_posix()) for f in p.glob("**/*.*")] 32 | missing = list(filter((lambda f: f not in flist), allfiles)) 33 | extras = list(filter((lambda f: f not in allfiles), flist)) 34 | if len(missing) > 0 or len(extras) > 0: 35 | print("Error!") 36 | for f in missing: 37 | print("MISSING: " + str(f)) 38 | for f in extras: 39 | print("EXTRA: " + str(f)) 40 | sys.exit(1) 41 | else: 42 | print("OK!") 43 | 44 | 45 | test() 46 | test("test/build_profile.json") 47 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # redot-cpp integration test 2 | 3 | This project is used to perform integration testing of the redot-cpp 4 | extension, to validate PRs and implemented APIs. 5 | 6 | ## License 7 | 8 | This is free and unencumbered software released into the public domain. 9 | 10 | Anyone is free to copy, modify, publish, use, compile, sell, or 11 | distribute this software, either in source code form or as a compiled 12 | binary, for any purpose, commercial or non-commercial, and by any 13 | means. 14 | 15 | In jurisdictions that recognize copyright laws, the author or authors 16 | of this software dedicate any and all copyright interest in the 17 | software to the public domain. We make this dedication for the benefit 18 | of the public at large and to the detriment of our heirs and 19 | successors. We intend this dedication to be an overt act of 20 | relinquishment in perpetuity of all present and future rights to this 21 | software under copyright law. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 26 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 27 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 28 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 29 | OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | For more information, please refer to 32 | -------------------------------------------------------------------------------- /SConstruct: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | 5 | EnsureSConsVersion(4, 0) 6 | 7 | 8 | try: 9 | Import("env") 10 | except Exception: 11 | # Default tools with no platform defaults to gnu toolchain. 12 | # We apply platform specific toolchains via our custom tools. 13 | env = Environment(tools=["default"], PLATFORM="") 14 | 15 | env.PrependENVPath("PATH", os.getenv("PATH")) 16 | 17 | # Custom options and profile flags. 18 | customs = ["custom.py"] 19 | try: 20 | customs += Import("customs") 21 | except Exception: 22 | pass 23 | profile = ARGUMENTS.get("profile", "") 24 | if profile: 25 | if os.path.isfile(profile): 26 | customs.append(profile) 27 | elif os.path.isfile(profile + ".py"): 28 | customs.append(profile + ".py") 29 | opts = Variables(customs, ARGUMENTS) 30 | cpp_tool = Tool("godotcpp", toolpath=["tools"]) 31 | cpp_tool.options(opts, env) 32 | opts.Update(env) 33 | 34 | Help(opts.GenerateHelpText(env)) 35 | 36 | # Detect and print a warning listing unknown SCons variables to ease troubleshooting. 37 | unknown = opts.UnknownVariables() 38 | if unknown: 39 | print("WARNING: Unknown SCons variables were passed and will be ignored:") 40 | for item in unknown.items(): 41 | print(" " + item[0] + "=" + item[1]) 42 | 43 | scons_cache_path = os.environ.get("SCONS_CACHE") 44 | if scons_cache_path is not None: 45 | CacheDir(scons_cache_path) 46 | Decider("MD5") 47 | 48 | cpp_tool.generate(env) 49 | library = env.GodotCPP() 50 | 51 | Return("env") 52 | -------------------------------------------------------------------------------- /tools/my_spawn.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def exists(env): 5 | return os.name == "nt" 6 | 7 | 8 | # Workaround for MinGW. See: 9 | # http://www.scons.org/wiki/LongCmdLinesOnWin32 10 | def configure(env): 11 | import subprocess 12 | 13 | def mySubProcess(cmdline, env): 14 | # print "SPAWNED : " + cmdline 15 | startupinfo = subprocess.STARTUPINFO() 16 | startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW 17 | proc = subprocess.Popen( 18 | cmdline, 19 | stdin=subprocess.PIPE, 20 | stdout=subprocess.PIPE, 21 | stderr=subprocess.PIPE, 22 | startupinfo=startupinfo, 23 | shell=False, 24 | env=env, 25 | ) 26 | data, err = proc.communicate() 27 | rv = proc.wait() 28 | if rv: 29 | print("=====") 30 | print(err.decode("utf-8")) 31 | print("=====") 32 | return rv 33 | 34 | def mySpawn(sh, escape, cmd, args, env): 35 | newargs = " ".join(args[1:]) 36 | cmdline = cmd + " " + newargs 37 | 38 | rv = 0 39 | if len(cmdline) > 32000 and cmd.endswith("ar"): 40 | cmdline = cmd + " " + args[1] + " " + args[2] + " " 41 | for i in range(3, len(args)): 42 | rv = mySubProcess(cmdline + args[i], env) 43 | if rv: 44 | break 45 | else: 46 | rv = mySubProcess(cmdline, env) 47 | 48 | return rv 49 | 50 | env["SPAWN"] = mySpawn 51 | env.Replace(ARFLAGS=["q"]) 52 | -------------------------------------------------------------------------------- /misc/scripts/make_tarball.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ ! -e "version.py" ]; then 4 | echo "This script should be ran from the root folder of the Redot repository." 5 | exit 1 6 | fi 7 | 8 | while getopts "h?sv:g:" opt; do 9 | case "$opt" in 10 | h|\?) 11 | echo "Usage: $0 [OPTIONS...]" 12 | echo 13 | echo " -s script friendly file name (godot.tar.gz)" 14 | echo " -v redot version for file name (e.g. 4.0-stable)" 15 | echo " -g git treeish to archive (e.g. master)" 16 | echo 17 | exit 1 18 | ;; 19 | s) 20 | script_friendly_name=1 21 | ;; 22 | v) 23 | godot_version=$OPTARG 24 | ;; 25 | g) 26 | git_treeish=$OPTARG 27 | ;; 28 | esac 29 | done 30 | 31 | if [ ! -z "$git_treeish" ]; then 32 | HEAD=$(git rev-parse $git_treeish) 33 | else 34 | HEAD=$(git rev-parse HEAD) 35 | fi 36 | 37 | if [ ! -z "$script_friendly_name" ]; then 38 | NAME=redot 39 | else 40 | if [ ! -z "$godot_version" ]; then 41 | NAME=redot-$godot_version 42 | else 43 | NAME=redot-$HEAD 44 | fi 45 | fi 46 | 47 | CURDIR=$(pwd) 48 | TMPDIR=$(mktemp -d -t redot-XXXXXX) 49 | 50 | echo "Generating tarball for revision $HEAD with folder name '$NAME'." 51 | echo 52 | echo "The tarball will be written to the parent folder:" 53 | echo " $(dirname $CURDIR)/$NAME.tar.gz" 54 | 55 | git archive $HEAD --prefix=$NAME/ -o $TMPDIR/$NAME.tar 56 | 57 | # Adding custom .git/HEAD to tarball so that we can generate VERSION_HASH. 58 | cd $TMPDIR 59 | mkdir -p $NAME/.git 60 | echo $HEAD > $NAME/.git/HEAD 61 | tar -uf $NAME.tar $NAME 62 | 63 | cd $CURDIR 64 | gzip -c $TMPDIR/$NAME.tar > ../$NAME.tar.gz 65 | 66 | rm -rf $TMPDIR 67 | -------------------------------------------------------------------------------- /test/SConstruct: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | env = SConscript("../SConstruct") 4 | 5 | # For the reference: 6 | # - CCFLAGS are compilation flags shared between C and C++ 7 | # - CFLAGS are for C-specific compilation flags 8 | # - CXXFLAGS are for C++-specific compilation flags 9 | # - CPPFLAGS are for pre-processor flags 10 | # - CPPDEFINES are for pre-processor defines 11 | # - LINKFLAGS are for linking flags 12 | 13 | # tweak this if you want to use different folders, or more folders, to store your source code in. 14 | env.Append(CPPPATH=["src/"]) 15 | sources = Glob("src/*.cpp") 16 | 17 | if env["target"] in ["editor", "template_debug"]: 18 | doc_data = env.GodotCPPDocData("src/gen/doc_data.gen.cpp", source=Glob("doc_classes/*.xml")) 19 | sources.append(doc_data) 20 | 21 | if env["platform"] == "macos": 22 | library = env.SharedLibrary( 23 | "project/bin/libgdexample.{}.{}.framework/libgdexample.{}.{}".format( 24 | env["platform"], env["target"], env["platform"], env["target"] 25 | ), 26 | source=sources, 27 | ) 28 | elif env["platform"] == "ios": 29 | if env["ios_simulator"]: 30 | library = env.StaticLibrary( 31 | "project/bin/libgdexample.{}.{}.simulator.a".format(env["platform"], env["target"]), 32 | source=sources, 33 | ) 34 | else: 35 | library = env.StaticLibrary( 36 | "project/bin/libgdexample.{}.{}.a".format(env["platform"], env["target"]), 37 | source=sources, 38 | ) 39 | else: 40 | library = env.SharedLibrary( 41 | "project/bin/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]), 42 | source=sources, 43 | ) 44 | 45 | env.NoCache(library) 46 | Default(library) 47 | -------------------------------------------------------------------------------- /test/project/test_base.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | var test_passes := 0 4 | var test_failures := 0 5 | 6 | func __get_stack_frame(): 7 | var me = get_script() 8 | for s in get_stack(): 9 | if s.source == me.resource_path: 10 | return s 11 | return null 12 | 13 | func __assert_pass(): 14 | test_passes += 1 15 | 16 | func __assert_fail(): 17 | test_failures += 1 18 | var s = __get_stack_frame() 19 | if s != null: 20 | print_rich ("[color=red] == FAILURE: In function %s() from '%s' on line %s[/color]" % [s.function, s.source, s.line]) 21 | else: 22 | print_rich ("[color=red] == FAILURE (run with --debug to get more information!) ==[/color]") 23 | 24 | func assert_equal(actual, expected): 25 | if actual == expected: 26 | __assert_pass() 27 | else: 28 | __assert_fail() 29 | print (" |-> Expected '%s' but got '%s'" % [expected, actual]) 30 | 31 | func assert_true(v): 32 | assert_equal(v, true) 33 | 34 | func assert_false(v): 35 | assert_equal(v, false) 36 | 37 | func assert_not_equal(actual, expected): 38 | if actual != expected: 39 | __assert_pass() 40 | else: 41 | __assert_fail() 42 | print (" |-> Expected '%s' NOT to equal '%s'" % [expected, actual]) 43 | 44 | func exit_with_status() -> void: 45 | var success: bool = (test_failures == 0) 46 | print ("") 47 | print_rich ("[color=%s] ==== TESTS FINISHED ==== [/color]" % ("green" if success else "red")) 48 | print ("") 49 | print_rich (" PASSES: [color=green]%s[/color]" % test_passes) 50 | print_rich (" FAILURES: [color=red]%s[/color]" % test_failures) 51 | print ("") 52 | 53 | if success: 54 | print_rich("[color=green] ******** PASSED ******** [/color]") 55 | else: 56 | print_rich("[color=red] ******** FAILED ********[/color]") 57 | print("") 58 | 59 | get_tree().quit(0 if success else 1) 60 | -------------------------------------------------------------------------------- /test/src/register_types.cpp: -------------------------------------------------------------------------------- 1 | /* godot-cpp integration testing project. 2 | * 3 | * This is free and unencumbered software released into the public domain. 4 | */ 5 | 6 | #include "register_types.h" 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "example.h" 15 | #include "tests.h" 16 | 17 | using namespace godot; 18 | 19 | void initialize_example_module(ModuleInitializationLevel p_level) { 20 | if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { 21 | return; 22 | } 23 | 24 | GDREGISTER_CLASS(ExampleRef); 25 | GDREGISTER_CLASS(ExampleMin); 26 | GDREGISTER_CLASS(Example); 27 | GDREGISTER_VIRTUAL_CLASS(ExampleVirtual); 28 | GDREGISTER_ABSTRACT_CLASS(ExampleAbstractBase); 29 | GDREGISTER_CLASS(ExampleConcrete); 30 | GDREGISTER_CLASS(ExampleBase); 31 | GDREGISTER_CLASS(ExampleChild); 32 | GDREGISTER_RUNTIME_CLASS(ExampleRuntime); 33 | GDREGISTER_CLASS(ExamplePrzykład); 34 | } 35 | 36 | void uninitialize_example_module(ModuleInitializationLevel p_level) { 37 | if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { 38 | return; 39 | } 40 | } 41 | 42 | extern "C" { 43 | // Initialization. 44 | GDExtensionBool GDE_EXPORT example_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) { 45 | godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization); 46 | 47 | init_obj.register_initializer(initialize_example_module); 48 | init_obj.register_terminator(uninitialize_example_module); 49 | init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE); 50 | 51 | return init_obj.init(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /cmake/android.cmake: -------------------------------------------------------------------------------- 1 | #[=======================================================================[.rst: 2 | Android 3 | ------- 4 | 5 | This file contains functions for options and configuration for targeting the 6 | Android platform 7 | 8 | Configuration of the Android toolchain is done using toolchain files, 9 | CMakePresets, or variables on the command line. 10 | 11 | The `Android SDK`_ provides toolchain files to help with configuration. 12 | 13 | CMake has its own `built-in support`_ for cross compiling to the 14 | Android platforms. 15 | 16 | .. warning:: 17 | 18 | Android does not support or test the CMake built-in workflow, recommend 19 | using their toolchain file. 20 | 21 | .. _Android SDK:https://developer.android.com/ndk/guides/cmake 22 | 23 | .. _built-in support:https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android 24 | 25 | There is further information and examples in the doc/cmake.rst file. 26 | 27 | ]=======================================================================] 28 | 29 | #[============================[ Android Options ]============================] 30 | function(android_options) 31 | #[[ Options from SCons 32 | 33 | The options below are managed by CMake toolchain files, doc.cmake.rst has 34 | more information 35 | 36 | android_api_level : Target Android API level. 37 | Default = 21 38 | 39 | ANDROID_HOME : Path to your Android SDK installation. 40 | Default = os.environ.get("ANDROID_HOME", os.environ.get("ANDROID_SDK_ROOT") 41 | ]] 42 | endfunction() 43 | 44 | #[===========================[ Target Generation ]===========================] 45 | function(android_generate) 46 | target_compile_definitions(godot-cpp PUBLIC ANDROID_ENABLED UNIX_ENABLED) 47 | 48 | common_compiler_flags() 49 | endfunction() 50 | -------------------------------------------------------------------------------- /cmake/emsdkHack.cmake: -------------------------------------------------------------------------------- 1 | #[=======================================================================[.rst: 2 | emsdkHack 3 | --------- 4 | 5 | The Emscripten platform doesn't support the use of shared libraries as known by cmake. 6 | 7 | * https://github.com/emscripten-core/emscripten/issues/15276 8 | * https://github.com/emscripten-core/emscripten/issues/17804 9 | 10 | This workaround only works due to the way the cmake scripts are loaded. 11 | 12 | Prior to the use of ``project( ... )`` directive we need to set 13 | ``CMAKE_PROJECT_INCLUDE=cmake/emscripten.cmake``. 14 | This file will be loaded after the toolchain overriding the settings that 15 | prevent shared library building. 16 | 17 | CMAKE_PROJECT_INCLUDE was Added in version 3.15. 18 | ``CMAKE_PROJECT__INCLUDE`` was Added in version 3.17: 19 | 20 | More information on cmake's `code injection`_ 21 | 22 | .. _code injection:https://cmake.org/cmake/help/latest/command/project.html#code-injection 23 | 24 | Overwrite Shared Library Properties to allow shared libs to be generated. 25 | ]=======================================================================] 26 | if(EMSCRIPTEN) 27 | set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE) 28 | set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-sSIDE_MODULE=1") 29 | set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-sSIDE_MODULE=1") 30 | set(CMAKE_SHARED_LIBRARY_SUFFIX) # remove the suffix from the shared lib 31 | set(CMAKE_STRIP FALSE) # used by default in pybind11 on .so modules 32 | 33 | # The Emscripten toolchain sets the default value for EMSCRIPTEN_SYSTEM_PROCESSOR to x86 34 | # and copies that to CMAKE_SYSTEM_PROCESSOR. We don't want that. 35 | set(CMAKE_SYSTEM_PROCESSOR "wasm32") 36 | # the above prevents the need for logic like: 37 | #if( ${CMAKE_SYSTEM_NAME} STREQUAL Emscripten ) 38 | # set( SYSTEM_ARCH wasm32 ) 39 | #endif () 40 | endif() 41 | -------------------------------------------------------------------------------- /doc_source_generator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import glob 4 | import os 5 | import zlib 6 | 7 | 8 | def generate_doc_source(dst, source): 9 | g = open(dst, "w", encoding="utf-8") 10 | buf = "" 11 | docbegin = "" 12 | docend = "" 13 | for src in source: 14 | src_path = str(src) 15 | if not src_path.endswith(".xml"): 16 | continue 17 | with open(src_path, "r", encoding="utf-8") as f: 18 | content = f.read() 19 | buf += content 20 | 21 | buf = (docbegin + buf + docend).encode("utf-8") 22 | decomp_size = len(buf) 23 | 24 | # Use maximum zlib compression level to further reduce file size 25 | # (at the cost of initial build times). 26 | buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION) 27 | 28 | g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") 29 | g.write("\n") 30 | g.write("#include \n") 31 | g.write("\n") 32 | 33 | g.write('static const char *_doc_data_hash = "' + str(hash(buf)) + '";\n') 34 | g.write("static const int _doc_data_uncompressed_size = " + str(decomp_size) + ";\n") 35 | g.write("static const int _doc_data_compressed_size = " + str(len(buf)) + ";\n") 36 | g.write("static const unsigned char _doc_data_compressed[] = {\n") 37 | for i in range(len(buf)): 38 | g.write("\t" + str(buf[i]) + ",\n") 39 | g.write("};\n") 40 | g.write("\n") 41 | 42 | g.write( 43 | "static godot::internal::DocDataRegistration _doc_data_registration(_doc_data_hash, _doc_data_uncompressed_size, _doc_data_compressed_size, _doc_data_compressed);\n" 44 | ) 45 | g.write("\n") 46 | 47 | g.close() 48 | 49 | 50 | def scons_generate_doc_source(target, source, env): 51 | generate_doc_source(str(target[0]), source) 52 | 53 | 54 | def generate_doc_source_from_directory(target, directory): 55 | generate_doc_source(target, glob.glob(os.path.join(directory, "*.xml"))) 56 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | default_language_version: 2 | python: python3 3 | 4 | exclude: | 5 | (?x)^( 6 | gdextension/extension_api\.json| 7 | gdextension/gdextension_interface\.h 8 | )$ 9 | 10 | repos: 11 | - repo: https://github.com/pre-commit/mirrors-clang-format 12 | rev: v17.0.6 13 | hooks: 14 | - id: clang-format 15 | 16 | - repo: https://github.com/astral-sh/ruff-pre-commit 17 | rev: v0.4.4 18 | hooks: 19 | - id: ruff 20 | args: [--fix] 21 | - id: ruff-format 22 | 23 | - repo: https://github.com/pre-commit/mirrors-mypy 24 | rev: v0.971 25 | hooks: 26 | - id: mypy 27 | files: \.py$ 28 | types_or: [text] 29 | 30 | - repo: https://github.com/codespell-project/codespell 31 | rev: v2.3.0 32 | hooks: 33 | - id: codespell 34 | additional_dependencies: [tomli] 35 | 36 | - repo: https://github.com/BlankSpruce/gersemi 37 | rev: 0.18.2 38 | hooks: 39 | - id: gersemi 40 | args: ["-i", "--no-warn-about-unknown-commands", "-l", "120"] 41 | 42 | - repo: local 43 | hooks: 44 | - id: copyright-headers 45 | name: copyright-headers 46 | language: python 47 | entry: python misc/scripts/copyright_headers.py 48 | files: \.(c|h)pp$ 49 | exclude: ^test/ 50 | 51 | - id: header-guards 52 | name: header-guards 53 | language: python 54 | entry: python misc/scripts/header_guards.py 55 | files: \.hpp$ 56 | exclude: ^test/ 57 | 58 | - id: file-format 59 | name: file-format 60 | language: python 61 | entry: python misc/scripts/file_format.py 62 | types_or: [text] 63 | 64 | - id: check-get-file-list 65 | name: check-get-file-list 66 | language: python 67 | entry: python misc/scripts/check_get_file_list.py 68 | pass_filenames: false 69 | always_run: true 70 | stages: [manual] 71 | -------------------------------------------------------------------------------- /tools/linux.py: -------------------------------------------------------------------------------- 1 | import common_compiler_flags 2 | from SCons.Tool import clang, clangxx 3 | from SCons.Variables import BoolVariable 4 | 5 | 6 | def options(opts): 7 | opts.Add(BoolVariable("use_llvm", "Use the LLVM compiler - only effective when targeting Linux", False)) 8 | opts.Add(BoolVariable("use_static_cpp", "Link libgcc and libstdc++ statically for better portability", True)) 9 | 10 | 11 | def exists(env): 12 | return True 13 | 14 | 15 | def generate(env): 16 | if env["use_llvm"]: 17 | clang.generate(env) 18 | clangxx.generate(env) 19 | elif env.use_hot_reload: 20 | # Required for extensions to truly unload. 21 | env.Append(CXXFLAGS=["-fno-gnu-unique"]) 22 | 23 | env.Append(CCFLAGS=["-fPIC", "-Wwrite-strings"]) 24 | env.Append(LINKFLAGS=["-Wl,-R,'$$ORIGIN'"]) 25 | 26 | if env["arch"] == "x86_64": 27 | # -m64 and -m32 are x86-specific already, but it doesn't hurt to 28 | # be clear and also specify -march=x86-64. Similar with 32-bit. 29 | env.Append(CCFLAGS=["-m64", "-march=x86-64"]) 30 | env.Append(LINKFLAGS=["-m64", "-march=x86-64"]) 31 | elif env["arch"] == "x86_32": 32 | env.Append(CCFLAGS=["-m32", "-march=i686"]) 33 | env.Append(LINKFLAGS=["-m32", "-march=i686"]) 34 | elif env["arch"] == "arm64": 35 | env.Append(CCFLAGS=["-march=armv8-a"]) 36 | env.Append(LINKFLAGS=["-march=armv8-a"]) 37 | elif env["arch"] == "rv64": 38 | env.Append(CCFLAGS=["-march=rv64gc"]) 39 | env.Append(LINKFLAGS=["-march=rv64gc"]) 40 | 41 | # Link statically for portability 42 | if env["use_static_cpp"]: 43 | env.Append(LINKFLAGS=["-static-libgcc", "-static-libstdc++"]) 44 | 45 | env.Append(CPPDEFINES=["LINUX_ENABLED", "UNIX_ENABLED"]) 46 | 47 | # Refer to https://github.com/godotengine/godot/blob/master/platform/linuxbsd/detect.py 48 | if env["lto"] == "auto": 49 | env["lto"] = "full" 50 | 51 | common_compiler_flags.generate(env) 52 | -------------------------------------------------------------------------------- /tools/web.py: -------------------------------------------------------------------------------- 1 | import common_compiler_flags 2 | from SCons.Util import WhereIs 3 | 4 | 5 | def exists(env): 6 | return WhereIs("emcc") is not None 7 | 8 | 9 | def generate(env): 10 | if env["arch"] not in ("wasm32"): 11 | print("Only wasm32 supported on web. Exiting.") 12 | env.Exit(1) 13 | 14 | # Emscripten toolchain 15 | env["CC"] = "emcc" 16 | env["CXX"] = "em++" 17 | env["AR"] = "emar" 18 | env["RANLIB"] = "emranlib" 19 | 20 | # Use TempFileMunge since some AR invocations are too long for cmd.exe. 21 | # Use POSIX-style paths, required with TempFileMunge. 22 | env["ARCOM_POSIX"] = env["ARCOM"].replace("$TARGET", "$TARGET.posix").replace("$SOURCES", "$SOURCES.posix") 23 | env["ARCOM"] = "${TEMPFILE(ARCOM_POSIX)}" 24 | 25 | # All intermediate files are just object files. 26 | env["OBJSUFFIX"] = ".o" 27 | env["SHOBJSUFFIX"] = ".o" 28 | 29 | # Static libraries clang-style. 30 | env["LIBPREFIX"] = "lib" 31 | env["LIBSUFFIX"] = ".a" 32 | 33 | # Shared library as wasm. 34 | env["SHLIBSUFFIX"] = ".wasm" 35 | 36 | # Thread support (via SharedArrayBuffer). 37 | if env["threads"]: 38 | env.Append(CCFLAGS=["-sUSE_PTHREADS=1"]) 39 | env.Append(LINKFLAGS=["-sUSE_PTHREADS=1"]) 40 | 41 | # Build as side module (shared library). 42 | env.Append(CCFLAGS=["-sSIDE_MODULE=1"]) 43 | env.Append(LINKFLAGS=["-sSIDE_MODULE=1"]) 44 | 45 | # Enable WebAssembly BigInt <-> i64 conversion. 46 | # This must match the flag used to build Godot (true in official builds since 4.3) 47 | env.Append(LINKFLAGS=["-sWASM_BIGINT"]) 48 | 49 | # Force wasm longjmp mode. 50 | env.Append(CCFLAGS=["-sSUPPORT_LONGJMP='wasm'"]) 51 | env.Append(LINKFLAGS=["-sSUPPORT_LONGJMP='wasm'"]) 52 | 53 | env.Append(CPPDEFINES=["WEB_ENABLED", "UNIX_ENABLED"]) 54 | 55 | # Refer to https://github.com/godotengine/godot/blob/master/platform/web/detect.py 56 | if env["lto"] == "auto": 57 | env["lto"] = "full" 58 | 59 | common_compiler_flags.generate(env) 60 | -------------------------------------------------------------------------------- /.github/actions/setup-godot-cpp/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup godot-cpp 2 | description: Setup build dependencies for godot-cpp. 3 | 4 | inputs: 5 | platform: 6 | required: true 7 | description: Target platform. 8 | em-version: 9 | default: 3.1.62 10 | description: Emscripten version. 11 | windows-compiler: 12 | required: true 13 | description: The compiler toolchain to use on Windows ('mingw' or 'msvc'). 14 | type: choice 15 | options: 16 | - mingw 17 | - msvc 18 | default: mingw 19 | mingw-version: 20 | default: 12.2.0 21 | description: MinGW version. 22 | ndk-version: 23 | default: r23c 24 | description: Android NDK version. 25 | buildtool: 26 | default: scons 27 | description: scons or cmake 28 | scons-version: 29 | default: 4.4.0 30 | description: SCons version. 31 | 32 | 33 | runs: 34 | using: composite 35 | steps: 36 | - name: Setup Python (for SCons) 37 | uses: actions/setup-python@v5 38 | with: 39 | python-version: 3.x 40 | 41 | - name: Setup Android dependencies 42 | if: inputs.platform == 'android' 43 | uses: nttld/setup-ndk@v1 44 | with: 45 | ndk-version: ${{ inputs.ndk-version }} 46 | link-to-sdk: true 47 | 48 | - name: Setup Web dependencies 49 | if: inputs.platform == 'web' 50 | uses: mymindstorm/setup-emsdk@v14 51 | with: 52 | version: ${{ inputs.em-version }} 53 | no-cache: true 54 | 55 | - name: Setup MinGW for Windows/MinGW build 56 | if: inputs.platform == 'windows' && inputs.windows-compiler == 'mingw' 57 | uses: egor-tensin/setup-mingw@v2 58 | with: 59 | version: ${{ inputs.mingw-version }} 60 | 61 | - name: Setup SCons 62 | if: ${{ inputs.buildtool == 'scons' }} 63 | shell: bash 64 | run: | 65 | python -c "import sys; print(sys.version)" 66 | python -m pip install scons==${{ inputs.scons-version }} 67 | scons --version 68 | 69 | - name: Install Ninja 70 | if: ${{ inputs.buildtool == 'cmake' }} 71 | uses: ashutoshvarma/setup-ninja@master 72 | -------------------------------------------------------------------------------- /.github/workflows/runner.yml: -------------------------------------------------------------------------------- 1 | name: 🔗 GHA 2 | on: [push, pull_request, merge_group] 3 | 4 | concurrency: 5 | group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-runner 6 | cancel-in-progress: true 7 | 8 | jobs: 9 | # First stage: Only static checks, fast and prevent expensive builds from running. 10 | 11 | static-checks: 12 | name: 📊 Static Checks 13 | if: '!vars.DISABLE_GODOT_CI' 14 | uses: ./.github/workflows/static_checks.yml 15 | 16 | # Second stage: Review code changes 17 | changes: 18 | name: Analyze Changes 19 | needs: static-checks 20 | runs-on: ubuntu-latest 21 | outputs: 22 | sources: ${{ steps.filter.outputs.sources_any_changed }} 23 | scons: ${{ steps.filter.outputs.scons_any_changed }} 24 | cmake: ${{ steps.filter.outputs.cmake_any_changed }} 25 | steps: 26 | - uses: actions/checkout@v4 27 | with: 28 | submodules: recursive 29 | - uses: tj-actions/changed-files@v45 30 | id: filter 31 | with: 32 | files_yaml: | 33 | sources: 34 | - '.github/workflows/*.yml' 35 | - '**/*.py' 36 | - '**/*.cpp' 37 | - '**/*.h' 38 | - 'test/build_profile.json' 39 | - 'gdextension/extension_api.json' 40 | scons: 41 | - '**/SConstruct' 42 | - '**/SCsub' 43 | - '**/*.py' 44 | cmake: 45 | - '**/CMakeLists.txt' 46 | - '**/*.cmake' 47 | - name: echo sources changed 48 | run: | 49 | echo sources ${{ steps.filter.outputs.sources_any_modified }} 50 | echo scons ${{ steps.filter.outputs.scons_any_modified }} 51 | echo cmake ${{ steps.filter.outputs.cmake_any_modified }} 52 | 53 | # Third stage: Run all the builds and some of the tests. 54 | 55 | ci-scons: 56 | name: 🛠️ SCons CI 57 | needs: changes 58 | if: ${{ needs.changes.outputs.scons == 'true' || needs.changes.outputs.sources == 'true' }} 59 | uses: ./.github/workflows/ci-scons.yml 60 | 61 | ci-cmake: 62 | name: 🛠️ CMake CI 63 | needs: changes 64 | if: ${{ needs.changes.outputs.cmake == 'true' || needs.changes.outputs.sources == 'true' }} 65 | uses: ./.github/workflows/ci-cmake.yml 66 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #[=======================================================================[.rst: 2 | Integration Testing 3 | ------------------- 4 | 5 | The Test target used to validate changes in the GitHub CI. 6 | ]=======================================================================] 7 | 8 | message(STATUS "Testing Integration targets are enabled.") 9 | 10 | set(TARGET_NAME "godot-cpp-test") 11 | 12 | add_library(${TARGET_NAME} SHARED EXCLUDE_FROM_ALL) 13 | 14 | target_sources( 15 | ${TARGET_NAME} 16 | PRIVATE src/example.cpp src/example.h src/register_types.cpp src/register_types.h src/tests.h 17 | ) 18 | 19 | # conditionally add doc data to compile output 20 | if(GODOTCPP_TARGET MATCHES "editor|template_debug") 21 | file(GLOB_RECURSE DOC_XML LIST_DIRECTORIES NO CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/doc_classes/*.xml") 22 | target_doc_sources( ${TARGET_NAME} ${DOC_XML} ) 23 | endif() 24 | 25 | set(OUTPUT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/project/bin/") 26 | 27 | # Link to godot-cpp target 28 | target_link_libraries(${TARGET_NAME} PRIVATE godot-cpp) 29 | 30 | ### Get useful properties from godot-cpp target 31 | get_target_property(GODOTCPP_SUFFIX godot-cpp GODOTCPP_SUFFIX) 32 | 33 | # gersemi: off 34 | set_target_properties( 35 | ${TARGET_NAME} 36 | PROPERTIES 37 | CXX_STANDARD 17 38 | CXX_EXTENSIONS OFF 39 | CXX_VISIBILITY_PRESET ${GODOTCPP_SYMBOL_VISIBILITY} 40 | 41 | POSITION_INDEPENDENT_CODE ON 42 | BUILD_RPATH_USE_ORIGIN ON 43 | 44 | # Try to ensure only static libraries are selected to be linked to. 45 | LINK_SEARCH_START_STATIC ON 46 | LINK_SEARCH_END_STATIC ON 47 | 48 | # NOTE: Wrapping the output variables inside a generator expression 49 | # prevents msvc generator from adding addition Config Directories 50 | LIBRARY_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>" 51 | RUNTIME_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>" 52 | PDB_OUTPUT_DIRECTORY "$<1:${OUTPUT_DIR}>" #MSVC Only, ignored on other platforms 53 | 54 | PREFIX "lib" 55 | OUTPUT_NAME "gdexample${GODOTCPP_SUFFIX}" 56 | # TODO rename the file for both CMake and SCons 57 | 58 | # Some IDE's respect this property to logically group targets 59 | FOLDER "godot-cpp" 60 | ) 61 | # gersemi: on 62 | 63 | # CMAKE_SYSTEM_NAME refers to the target system 64 | if(CMAKE_SYSTEM_NAME STREQUAL Darwin) 65 | set_target_properties( 66 | ${TARGET_NAME} 67 | PROPERTIES SUFFIX "" OUTPUT_DIR "${OUTPUT_DIR}/libgdexample.macos.${GODOTCPP_TARGET}.framework" 68 | ) 69 | endif() 70 | -------------------------------------------------------------------------------- /test/project/example.gdextension: -------------------------------------------------------------------------------- 1 | [configuration] 2 | 3 | entry_symbol = "example_library_init" 4 | compatibility_minimum = "4.1" 5 | 6 | [libraries] 7 | 8 | macos.debug = "res://bin/libgdexample.macos.template_debug.framework" 9 | macos.release = "res://bin/libgdexample.macos.template_release.framework" 10 | windows.debug.x86_32 = "res://bin/libgdexample.windows.template_debug.x86_32.dll" 11 | windows.release.x86_32 = "res://bin/libgdexample.windows.template_release.x86_32.dll" 12 | windows.debug.x86_64 = "res://bin/libgdexample.windows.template_debug.x86_64.dll" 13 | windows.release.x86_64 = "res://bin/libgdexample.windows.template_release.x86_64.dll" 14 | windows.debug.arm64 = "res://bin/libgdexample.windows.template_debug.arm64.dll" 15 | windows.release.arm64 = "res://bin/libgdexample.windows.template_release.arm64.dll" 16 | linux.debug.x86_32 = "res://bin/libgdexample.linux.template_debug.x86_32.so" 17 | linux.release.x86_32 = "res://bin/libgdexample.linux.template_release.x86_32.so" 18 | linux.debug.x86_64 = "res://bin/libgdexample.linux.template_debug.x86_64.so" 19 | linux.release.x86_64 = "res://bin/libgdexample.linux.template_release.x86_64.so" 20 | linux.debug.arm32 = "res://bin/libgdexample.linux.template_debug.arm32.so" 21 | linux.release.arm32 = "res://bin/libgdexample.linux.template_release.arm32.so" 22 | linux.debug.arm64 = "res://bin/libgdexample.linux.template_debug.arm64.so" 23 | linux.release.arm64 = "res://bin/libgdexample.linux.template_release.arm64.so" 24 | linux.debug.rv64 = "res://bin/libgdexample.linux.template_debug.rv64.so" 25 | linux.release.rv64 = "res://bin/libgdexample.linux.template_release.rv64.so" 26 | android.debug.x86_64 = "res://bin/libgdexample.android.template_debug.x86_64.so" 27 | android.release.x86_64 = "res://bin/libgdexample.android.template_release.x86_64.so" 28 | android.debug.arm64 = "res://bin/libgdexample.android.template_debug.arm64.so" 29 | android.release.arm64 = "res://bin/libgdexample.android.template_release.arm64.so" 30 | ios.debug = "res://bin/libgdexample.ios.template_debug.xcframework" 31 | ios.release = "res://bin/libgdexample.ios.template_release.xcframework" 32 | web.debug.threads.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.wasm" 33 | web.release.threads.wasm32 = "res://bin/libgdexample.web.template_release.wasm32.wasm" 34 | web.debug.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.nothreads.wasm" 35 | web.release.wasm32 = "res://bin/libgdexample.web.template_release.wasm32.nothreads.wasm" 36 | 37 | [dependencies] 38 | ios.debug = { 39 | "res://bin/libredot-cpp.ios.template_debug.xcframework": "" 40 | } 41 | ios.release = { 42 | "res://bin/libredot-cpp.ios.template_release.xcframework": "" 43 | } 44 | -------------------------------------------------------------------------------- /src/core/print_string.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* print_string.cpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #include 34 | 35 | #include 36 | 37 | namespace godot { 38 | bool is_print_verbose_enabled() { 39 | return OS::get_singleton()->is_stdout_verbose(); 40 | } 41 | } // namespace godot 42 | -------------------------------------------------------------------------------- /misc/scripts/check_ci_log.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | 6 | if len(sys.argv) < 2: 7 | print("ERROR: You must run program with file name as argument.") 8 | sys.exit(50) 9 | 10 | fname = sys.argv[1] 11 | 12 | with open(fname.strip(), "r", encoding="utf-8") as fileread: 13 | file_contents = fileread.read() 14 | 15 | # If find "ERROR: AddressSanitizer:", then happens invalid read or write 16 | # This is critical bug, so we need to fix this as fast as possible 17 | 18 | if file_contents.find("ERROR: AddressSanitizer:") != -1: 19 | print("FATAL ERROR: An incorrectly used memory was found.") 20 | sys.exit(51) 21 | 22 | # There is also possible, that program crashed with or without backtrace. 23 | 24 | if ( 25 | file_contents.find("Program crashed with signal") != -1 26 | or file_contents.find("Dumping the backtrace") != -1 27 | or file_contents.find("Segmentation fault (core dumped)") != -1 28 | or file_contents.find("Aborted (core dumped)") != -1 29 | or file_contents.find("terminate called without an active exception") != -1 30 | ): 31 | print("FATAL ERROR: Redot has been crashed.") 32 | sys.exit(52) 33 | 34 | # Finding memory leaks in Redot is quite difficult, because we need to take into 35 | # account leaks also in external libraries. They are usually provided without 36 | # debugging symbols, so the leak report from it usually has only 2/3 lines, 37 | # so searching for 5 element - "#4 0x" - should correctly detect the vast 38 | # majority of memory leaks 39 | 40 | if file_contents.find("ERROR: LeakSanitizer:") != -1: 41 | if file_contents.find("#4 0x") != -1: 42 | print("ERROR: Memory leak was found") 43 | sys.exit(53) 44 | 45 | # It may happen that Redot detects leaking nodes/resources and removes them, so 46 | # this possibility should also be handled as a potential error, even if 47 | # LeakSanitizer doesn't report anything 48 | 49 | if file_contents.find("ObjectDB instances leaked at exit") != -1: 50 | print("ERROR: Memory leak was found") 51 | sys.exit(54) 52 | 53 | # In test project may be put several assert functions which will control if 54 | # project is executed with right parameters etc. which normally will not stop 55 | # execution of project 56 | 57 | if file_contents.find("Assertion failed") != -1: 58 | print("ERROR: Assertion failed in project, check execution log for more info") 59 | sys.exit(55) 60 | 61 | # For now Redot leaks a lot of rendering stuff so for now we just show info 62 | # about it and this needs to be re-enabled after fixing this memory leaks. 63 | 64 | if file_contents.find("were leaked") != -1 or file_contents.find("were never freed") != -1: 65 | print("WARNING: Memory leak was found") 66 | 67 | sys.exit(0) 68 | -------------------------------------------------------------------------------- /tools/macos.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | import common_compiler_flags 5 | 6 | 7 | def has_osxcross(): 8 | return "OSXCROSS_ROOT" in os.environ 9 | 10 | 11 | def options(opts): 12 | opts.Add("macos_deployment_target", "macOS deployment target", "default") 13 | opts.Add("macos_sdk_path", "macOS SDK path", "") 14 | if has_osxcross(): 15 | opts.Add("osxcross_sdk", "OSXCross SDK version", "darwin16") 16 | 17 | 18 | def exists(env): 19 | return sys.platform == "darwin" or has_osxcross() 20 | 21 | 22 | def generate(env): 23 | if env["arch"] not in ("universal", "arm64", "x86_64"): 24 | print("Only universal, arm64, and x86_64 are supported on macOS. Exiting.") 25 | env.Exit(1) 26 | 27 | if sys.platform == "darwin": 28 | # Use clang on macOS by default 29 | env["CXX"] = "clang++" 30 | env["CC"] = "clang" 31 | else: 32 | # OSXCross 33 | root = os.environ.get("OSXCROSS_ROOT", "") 34 | if env["arch"] == "arm64": 35 | basecmd = root + "/target/bin/arm64-apple-" + env["osxcross_sdk"] + "-" 36 | else: 37 | basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-" 38 | 39 | env["CC"] = basecmd + "clang" 40 | env["CXX"] = basecmd + "clang++" 41 | env["AR"] = basecmd + "ar" 42 | env["RANLIB"] = basecmd + "ranlib" 43 | env["AS"] = basecmd + "as" 44 | 45 | binpath = os.path.join(root, "target", "bin") 46 | if binpath not in env["ENV"]["PATH"]: 47 | # Add OSXCROSS bin folder to PATH (required for linking). 48 | env.PrependENVPath("PATH", binpath) 49 | 50 | # Common flags 51 | if env["arch"] == "universal": 52 | env.Append(LINKFLAGS=["-arch", "x86_64", "-arch", "arm64"]) 53 | env.Append(CCFLAGS=["-arch", "x86_64", "-arch", "arm64"]) 54 | else: 55 | env.Append(LINKFLAGS=["-arch", env["arch"]]) 56 | env.Append(CCFLAGS=["-arch", env["arch"]]) 57 | 58 | if env["macos_deployment_target"] != "default": 59 | env.Append(CCFLAGS=["-mmacosx-version-min=" + env["macos_deployment_target"]]) 60 | env.Append(LINKFLAGS=["-mmacosx-version-min=" + env["macos_deployment_target"]]) 61 | 62 | if env["macos_sdk_path"]: 63 | env.Append(CCFLAGS=["-isysroot", env["macos_sdk_path"]]) 64 | env.Append(LINKFLAGS=["-isysroot", env["macos_sdk_path"]]) 65 | 66 | env.Append(CPPDEFINES=["MACOS_ENABLED", "UNIX_ENABLED"]) 67 | 68 | # Refer to https://github.com/godotengine/godot/blob/master/platform/macos/detect.py 69 | # LTO benefits for macOS (size, performance) haven't been clearly established yet. 70 | if env["lto"] == "auto": 71 | env["lto"] = "none" 72 | 73 | common_compiler_flags.generate(env) 74 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10...3.17) 2 | 3 | #[=======================================================================[.rst: 4 | 5 | CMake Version requirements 6 | -------------------------- 7 | 8 | To enable use of the emscripten emsdk hack for pseudo shared library support 9 | without polluting options for consumers we need to use the 10 | CMAKE_PROJECT__INCLUDE which was introduced in version 3.17 11 | 12 | For more information check cmake/emsdkHack.cmake 13 | 14 | SCons Compatibility 15 | ------------------- 16 | 17 | There is an understandable conflict between build systems as they define 18 | similar concepts in different ways. When there isn't a 1:1 relationship, 19 | compromises need to be made to resolve those differences. 20 | 21 | As we are attempting to maintain feature parity, and ease of maintenance, these 22 | CMake scripts are built to resemble the SCons build system wherever possible. 23 | Where they are not, we will attempt to document common difference in 24 | doc/cmake.rst and platform specific differences in their respective 25 | cmake/.cmake file. 26 | 27 | The file structure and file content are made to match, if not in content then 28 | in spirit. The closer the two build systems look the easier they will be to 29 | maintain. 30 | 31 | Where the SCons additional scripts in the tools directory, The CMake scripts 32 | are in the cmake directory. 33 | 34 | For example; the tools/godotcpp.py is matched by the cmake/godotcpp.cmake file 35 | 36 | .. highlight:: python 37 | 38 | cpp_tool = Tool("godotcpp", toolpath=["tools"]) 39 | cpp_tool.options(opts, env) 40 | 41 | The CMake equivalent is below. 42 | ]=======================================================================] 43 | include(cmake/godotcpp.cmake) 44 | 45 | godotcpp_options() 46 | 47 | #[[ People are compiling godot by itself and expecting template_debug 48 | Replace this with PROJECT_IS_TOP_LEVEL, _IS_TOP_LEVEL when minimum reaches 3.21 49 | ]] 50 | if(NOT PROJECT_NAME) 51 | set(GODOTCPP_IS_TOP_LEVEL ON) 52 | endif() 53 | 54 | # Define our project. 55 | project( 56 | godot-cpp 57 | VERSION 4.4 58 | DESCRIPTION "C++ bindings for the Godot Engine's GDExtensions API." 59 | HOMEPAGE_URL "https://github.com/godotengine/godot-cpp" 60 | LANGUAGES CXX 61 | ) 62 | 63 | compiler_detection() 64 | godotcpp_generate() 65 | 66 | # Conditionally enable the godot-cpp.test. integration testing targets 67 | if(GODOTCPP_ENABLE_TESTING) 68 | add_subdirectory(test) 69 | endif() 70 | 71 | #[[ If this is the top level CMakeLists.txt, Generators which honor the 72 | USE_FOLDERS flag will organize godot-cpp targets under a subfolder named 73 | 'godot-cpp'. This is enable by default from CMake version 3.26 ]] 74 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 75 | -------------------------------------------------------------------------------- /src/variant/rect2i.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* rect2i.cpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #include 34 | 35 | #include 36 | #include 37 | 38 | namespace godot { 39 | 40 | Rect2i::operator String() const { 41 | return "[P: " + position.operator String() + ", S: " + size + "]"; 42 | } 43 | 44 | Rect2i::operator Rect2() const { 45 | return Rect2(position, size); 46 | } 47 | 48 | } // namespace godot 49 | -------------------------------------------------------------------------------- /include/godot_cpp/templates/spin_lock.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* spin_lock.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | #include 36 | 37 | namespace godot { 38 | 39 | class SpinLock { 40 | std::atomic_flag locked = ATOMIC_FLAG_INIT; 41 | 42 | public: 43 | _ALWAYS_INLINE_ void lock() { 44 | while (locked.test_and_set(std::memory_order_acquire)) { 45 | ; 46 | } 47 | } 48 | _ALWAYS_INLINE_ void unlock() { 49 | locked.clear(std::memory_order_release); 50 | } 51 | }; 52 | 53 | } // namespace godot 54 | -------------------------------------------------------------------------------- /src/variant/variant_internal.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* variant_internal.cpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #include 34 | 35 | namespace godot { 36 | 37 | GDExtensionVariantGetInternalPtrFunc VariantInternal::get_internal_func[Variant::VARIANT_MAX]{}; 38 | 39 | void VariantInternal::init_bindings() { 40 | for (int i = 1; i < Variant::VARIANT_MAX; i++) { 41 | get_internal_func[i] = internal::gdextension_interface_variant_get_ptr_internal_getter((GDExtensionVariantType)i); 42 | } 43 | } 44 | 45 | } // namespace godot 46 | -------------------------------------------------------------------------------- /misc/scripts/header_guards.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | 6 | if len(sys.argv) < 2: 7 | print("Invalid usage of header_guards.py, it should be called with a path to one or multiple files.") 8 | sys.exit(1) 9 | 10 | changed = [] 11 | invalid = [] 12 | 13 | for file in sys.argv[1:]: 14 | header_start = -1 15 | header_end = -1 16 | 17 | with open(file.strip(), "rt", encoding="utf-8", newline="\n") as f: 18 | lines = f.readlines() 19 | 20 | for idx, line in enumerate(lines): 21 | sline = line.strip() 22 | 23 | if header_start < 0: 24 | if sline == "": # Skip empty lines at the top. 25 | continue 26 | 27 | if sline.startswith("/**********"): # Godot header starts this way. 28 | header_start = idx 29 | else: 30 | header_end = 0 # There is no Godot header. 31 | break 32 | else: 33 | if not sline.startswith(("*", "/*")): # Not in the Godot header anymore. 34 | header_end = idx + 1 # The guard should be two lines below the Godot header. 35 | break 36 | 37 | if (HEADER_CHECK_OFFSET := header_end) < 0 or HEADER_CHECK_OFFSET >= len(lines): 38 | invalid.append(file) 39 | continue 40 | 41 | if lines[HEADER_CHECK_OFFSET].startswith("#pragma once"): 42 | continue 43 | 44 | # Might be using legacy header guards. 45 | HEADER_BEGIN_OFFSET = HEADER_CHECK_OFFSET + 1 46 | HEADER_END_OFFSET = len(lines) - 1 47 | 48 | if HEADER_BEGIN_OFFSET >= HEADER_END_OFFSET: 49 | invalid.append(file) 50 | continue 51 | 52 | if ( 53 | lines[HEADER_CHECK_OFFSET].startswith("#ifndef") 54 | and lines[HEADER_BEGIN_OFFSET].startswith("#define") 55 | and lines[HEADER_END_OFFSET].startswith("#endif") 56 | ): 57 | lines[HEADER_CHECK_OFFSET] = "#pragma once" 58 | lines[HEADER_BEGIN_OFFSET] = "\n" 59 | lines.pop() 60 | with open(file, "wt", encoding="utf-8", newline="\n") as f: 61 | f.writelines(lines) 62 | changed.append(file) 63 | continue 64 | 65 | # Verify `#pragma once` doesn't exist at invalid location. 66 | misplaced = False 67 | for line in lines: 68 | if line.startswith("#pragma once"): 69 | misplaced = True 70 | break 71 | 72 | if misplaced: 73 | invalid.append(file) 74 | continue 75 | 76 | # Assume that we're simply missing a guard entirely. 77 | lines.insert(HEADER_CHECK_OFFSET, "#pragma once\n\n") 78 | with open(file, "wt", encoding="utf-8", newline="\n") as f: 79 | f.writelines(lines) 80 | changed.append(file) 81 | 82 | if changed: 83 | for file in changed: 84 | print(f"FIXED: {file}") 85 | if invalid: 86 | for file in invalid: 87 | print(f"REQUIRES MANUAL CHANGES: {file}") 88 | sys.exit(1) 89 | -------------------------------------------------------------------------------- /include/godot_cpp/core/math.compat.inc: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* math.compat.inc */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | 34 | #ifndef DISABLE_DEPRECATED 35 | 36 | namespace godot { 37 | 38 | #undef ABS 39 | 40 | // Generic ABS function, for math uses please use Math::abs. 41 | template 42 | [[deprecated("Use Math::abs instead")]] 43 | constexpr T ABS(T m_v) { 44 | return m_v < 0 ? -m_v : m_v; 45 | } 46 | 47 | } 48 | 49 | // To maintain compatibility an alias is defined outside the namespace. 50 | // Consider it deprecated. 51 | using real_t = godot::real_t; 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /include/godot_cpp/variant/array_helpers.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* array_helpers.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | namespace godot { 36 | namespace helpers { 37 | template 38 | T append_all(T appendable, ValueT value) { 39 | appendable.append(value); 40 | return appendable; 41 | } 42 | 43 | template 44 | T append_all(T appendable, ValueT value, Args... args) { 45 | appendable.append(value); 46 | return append_all(appendable, args...); 47 | } 48 | 49 | template 50 | T append_all(T appendable) { 51 | return appendable; 52 | } 53 | } // namespace helpers 54 | } // namespace godot 55 | -------------------------------------------------------------------------------- /include/godot_cpp/core/mutex_lock.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* mutex_lock.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | #include 36 | 37 | namespace godot { 38 | 39 | class MutexLock { 40 | const Mutex &mutex; 41 | 42 | public: 43 | _ALWAYS_INLINE_ explicit MutexLock(const Mutex &p_mutex) : 44 | mutex(p_mutex) { 45 | const_cast(&mutex)->lock(); 46 | } 47 | 48 | _ALWAYS_INLINE_ ~MutexLock() { 49 | const_cast(&mutex)->unlock(); 50 | } 51 | }; 52 | 53 | #define _THREAD_SAFE_CLASS_ mutable Mutex _thread_safe_; 54 | #define _THREAD_SAFE_METHOD_ MutexLock _thread_safe_method_(_thread_safe_); 55 | #define _THREAD_SAFE_LOCK_ _thread_safe_.lock(); 56 | #define _THREAD_SAFE_UNLOCK_ _thread_safe_.unlock(); 57 | 58 | } // namespace godot 59 | -------------------------------------------------------------------------------- /include/godot_cpp/classes/editor_plugin_registration.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* editor_plugin_registration.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | #include 36 | 37 | namespace godot { 38 | 39 | class EditorPlugin; 40 | class StringName; 41 | 42 | class EditorPlugins { 43 | private: 44 | static Vector plugin_classes; 45 | 46 | public: 47 | static void add_plugin_class(const StringName &p_class_name); 48 | static void remove_plugin_class(const StringName &p_class_name); 49 | static void deinitialize(GDExtensionInitializationLevel p_level); 50 | 51 | template 52 | static void add_by_type() { 53 | add_plugin_class(T::get_class_static()); 54 | } 55 | template 56 | static void remove_by_type() { 57 | remove_plugin_class(T::get_class_static()); 58 | } 59 | }; 60 | 61 | } // namespace godot 62 | -------------------------------------------------------------------------------- /include/godot_cpp/templates/search_array.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* search_array.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | #include 36 | 37 | namespace godot { 38 | 39 | template > 40 | class SearchArray { 41 | public: 42 | Comparator compare; 43 | 44 | inline int64_t bisect(const T *p_array, int64_t p_len, const T &p_value, bool p_before) const { 45 | int64_t lo = 0; 46 | int64_t hi = p_len; 47 | if (p_before) { 48 | while (lo < hi) { 49 | const int64_t mid = (lo + hi) / 2; 50 | if (compare(p_array[mid], p_value)) { 51 | lo = mid + 1; 52 | } else { 53 | hi = mid; 54 | } 55 | } 56 | } else { 57 | while (lo < hi) { 58 | const int64_t mid = (lo + hi) / 2; 59 | if (compare(p_value, p_array[mid])) { 60 | hi = mid; 61 | } else { 62 | lo = mid + 1; 63 | } 64 | } 65 | } 66 | return lo; 67 | } 68 | }; 69 | 70 | } // namespace godot 71 | -------------------------------------------------------------------------------- /include/godot_cpp/core/object_id.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* object_id.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | #include 36 | 37 | namespace godot { 38 | 39 | class ObjectID { 40 | uint64_t id = 0; 41 | 42 | public: 43 | _FORCE_INLINE_ bool is_ref_counted() const { return (id & (uint64_t(1) << 63)) != 0; } 44 | _FORCE_INLINE_ bool is_valid() const { return id != 0; } 45 | _FORCE_INLINE_ bool is_null() const { return id == 0; } 46 | _FORCE_INLINE_ operator uint64_t() const { return id; } 47 | _FORCE_INLINE_ operator int64_t() const { return id; } 48 | 49 | _FORCE_INLINE_ bool operator==(const ObjectID &p_id) const { return id == p_id.id; } 50 | _FORCE_INLINE_ bool operator!=(const ObjectID &p_id) const { return id != p_id.id; } 51 | _FORCE_INLINE_ bool operator<(const ObjectID &p_id) const { return id < p_id.id; } 52 | 53 | _FORCE_INLINE_ void operator=(int64_t p_int64) { id = p_int64; } 54 | _FORCE_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; } 55 | 56 | _FORCE_INLINE_ ObjectID() {} 57 | _FORCE_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; } 58 | _FORCE_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; } 59 | }; 60 | 61 | } // namespace godot 62 | -------------------------------------------------------------------------------- /include/godot_cpp/core/print_string.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* print_string.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | #include 36 | 37 | namespace godot { 38 | inline void print_error(const Variant &p_variant) { 39 | UtilityFunctions::printerr(p_variant); 40 | } 41 | 42 | inline void print_line(const Variant &p_variant) { 43 | UtilityFunctions::print(p_variant); 44 | } 45 | 46 | inline void print_line_rich(const Variant &p_variant) { 47 | UtilityFunctions::print_rich(p_variant); 48 | } 49 | 50 | template 51 | void print_error(const Variant &p_variant, Args... p_args) { 52 | UtilityFunctions::printerr(p_variant, p_args...); 53 | } 54 | 55 | template 56 | void print_line(const Variant &p_variant, Args... p_args) { 57 | UtilityFunctions::print(p_variant, p_args...); 58 | } 59 | 60 | template 61 | void print_line_rich(const Variant &p_variant, Args... p_args) { 62 | UtilityFunctions::print_rich(p_variant, p_args...); 63 | } 64 | 65 | template 66 | void print_verbose(const Variant &p_variant, Args... p_args) { 67 | UtilityFunctions::print_verbose(p_variant, p_args...); 68 | } 69 | 70 | bool is_print_verbose_enabled(); 71 | 72 | } // namespace godot 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot auto generated files 2 | *.gen.* 3 | .import/ 4 | .godot/ 5 | /gen/ 6 | 7 | # Godot 3.x ignores 8 | include/gen 9 | src/gen 10 | 11 | # Build configuration. 12 | /custom.py 13 | 14 | # Misc 15 | logs/* 16 | *.log 17 | 18 | # The default cache directory 19 | cache/ 20 | 21 | # Binaries 22 | *.o 23 | *.os 24 | *.so 25 | *.obj 26 | *.bc 27 | *.pyc 28 | *.dblite 29 | *.pdb 30 | *.lib 31 | bin 32 | *.config 33 | *.creator 34 | *.creator.user 35 | *.files 36 | *.includes 37 | *.idb 38 | 39 | # Gprof output 40 | gmon.out 41 | 42 | # Vim temp files 43 | *.swo 44 | *.swp 45 | 46 | # Qt project files 47 | *.config 48 | *.creator 49 | *.creator.* 50 | *.files 51 | *.includes 52 | *.cflags 53 | *.cxxflags 54 | 55 | # Eclipse CDT files 56 | .cproject 57 | .settings/ 58 | 59 | # Geany/geany-plugins files 60 | *.geany 61 | .geanyprj 62 | 63 | # Misc 64 | .DS_Store 65 | logs/ 66 | 67 | # for projects that use SCons for building: http://http://www.scons.org/ 68 | .sconf_temp 69 | .sconsign.dblite 70 | *.pyc 71 | 72 | # Visual C++ cache files 73 | ipch/ 74 | *.aps 75 | *.ncb 76 | *.opensdf 77 | *.sdf 78 | *.cachefile 79 | *.VC.db 80 | *.VC.opendb 81 | *.VC.VC.opendb 82 | enc_temp_folder/ 83 | 84 | # Visual Studio profiler 85 | *.psess 86 | *.vsp 87 | *.vspx 88 | 89 | # CodeLite project files 90 | *.project 91 | *.workspace 92 | .codelite/ 93 | 94 | # Windows Azure Build Output 95 | csx/ 96 | *.build.csdef 97 | 98 | # Windows Store app package directory 99 | AppPackages/ 100 | 101 | # Others 102 | sql/ 103 | *.[Cc]ache 104 | ClientBin/ 105 | [Ss]tyle[Cc]op.* 106 | ~$* 107 | *~ 108 | *.dbmdl 109 | *.dbproj.schemaview 110 | *.pfx 111 | *.publishsettings 112 | node_modules/ 113 | __pycache__/ 114 | 115 | # KDE 116 | .directory 117 | 118 | #Kdevelop project files 119 | *.kdev4 120 | 121 | # xCode 122 | xcuserdata 123 | 124 | # RIA/Silverlight projects 125 | Generated_Code/ 126 | 127 | # Backup & report files from converting an old project file to a newer 128 | # Visual Studio version. Backup files are not needed, because we have git ;-) 129 | _UpgradeReport_Files/ 130 | Backup*/ 131 | UpgradeLog*.XML 132 | UpgradeLog*.htm 133 | 134 | # SQL Server files 135 | App_Data/*.mdf 136 | App_Data/*.ldf 137 | 138 | # Business Intelligence projects 139 | *.rdl.data 140 | *.bim.layout 141 | *.bim_*.settings 142 | 143 | # Microsoft Fakes 144 | FakesAssemblies/ 145 | 146 | # ========================= 147 | # Windows detritus 148 | # ========================= 149 | 150 | # Windows image file caches 151 | Thumbs.db 152 | ehthumbs.db 153 | 154 | # Folder config file 155 | Desktop.ini 156 | 157 | # Recycle Bin used on file shares 158 | $RECYCLE.BIN/ 159 | logo.h 160 | *.autosave 161 | 162 | # https://github.com/github/gitignore/blob/master/Global/Tags.gitignore 163 | # Ignore tags created by etags, ctags, gtags (GNU global) and cscope 164 | TAGS 165 | !TAGS/ 166 | tags 167 | *.tags 168 | !tags/ 169 | gtags.files 170 | GTAGS 171 | GRTAGS 172 | GPATH 173 | cscope.files 174 | cscope.out 175 | cscope.in.out 176 | cscope.po.out 177 | godot.creator.* 178 | 179 | # Visual Studio 2017 and Visual Studio Code workspace folder 180 | /.vs 181 | /.vscode 182 | 183 | # Visual Studio Code workspace file 184 | *.code-workspace 185 | 186 | # Scons progress indicator 187 | .scons_node_count 188 | 189 | # ccls cache (https://github.com/MaskRay/ccls) 190 | .ccls-cache/ 191 | 192 | # compile commands (https://clang.llvm.org/docs/JSONCompilationDatabase.html) 193 | compile_commands.json 194 | 195 | # Python development 196 | .venv 197 | venv 198 | 199 | # Clion Configuration 200 | .idea/ 201 | cmake-build*/ 202 | 203 | # CMake related 204 | CMakeUserPresets.json 205 | -------------------------------------------------------------------------------- /include/godot_cpp/variant/callable_custom.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* callable_custom.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | #include 36 | #include 37 | 38 | namespace godot { 39 | 40 | class Object; 41 | 42 | class CallableCustomBase { 43 | public: 44 | virtual ObjectID get_object() const = 0; 45 | virtual int get_argument_count(bool &r_is_valid) const; 46 | virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const = 0; 47 | virtual ~CallableCustomBase() {} 48 | }; 49 | 50 | class CallableCustom : public CallableCustomBase { 51 | public: 52 | typedef bool (*CompareEqualFunc)(const CallableCustom *p_a, const CallableCustom *p_b); 53 | typedef bool (*CompareLessFunc)(const CallableCustom *p_a, const CallableCustom *p_b); 54 | 55 | virtual uint32_t hash() const = 0; 56 | virtual String get_as_text() const = 0; 57 | virtual CompareEqualFunc get_compare_equal_func() const = 0; 58 | virtual CompareLessFunc get_compare_less_func() const = 0; 59 | virtual bool is_valid() const; 60 | virtual ObjectID get_object() const = 0; 61 | virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, GDExtensionCallError &r_call_error) const = 0; 62 | }; 63 | 64 | } // namespace godot 65 | -------------------------------------------------------------------------------- /src/classes/editor_plugin_registration.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* editor_plugin_registration.cpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #include 34 | 35 | #include 36 | 37 | namespace godot { 38 | 39 | Vector EditorPlugins::plugin_classes; 40 | 41 | void EditorPlugins::add_plugin_class(const StringName &p_class_name) { 42 | ERR_FAIL_COND_MSG(plugin_classes.find(p_class_name) != -1, vformat("Editor plugin already registered: %s", p_class_name)); 43 | plugin_classes.push_back(p_class_name); 44 | internal::gdextension_interface_editor_add_plugin(p_class_name._native_ptr()); 45 | } 46 | 47 | void EditorPlugins::remove_plugin_class(const StringName &p_class_name) { 48 | int index = plugin_classes.find(p_class_name); 49 | ERR_FAIL_COND_MSG(index == -1, vformat("Editor plugin is not registered: %s", p_class_name)); 50 | plugin_classes.remove_at(index); 51 | internal::gdextension_interface_editor_remove_plugin(p_class_name._native_ptr()); 52 | } 53 | 54 | void EditorPlugins::deinitialize(GDExtensionInitializationLevel p_level) { 55 | if (p_level == GDEXTENSION_INITIALIZATION_EDITOR) { 56 | for (const StringName &class_name : plugin_classes) { 57 | internal::gdextension_interface_editor_remove_plugin(class_name._native_ptr()); 58 | } 59 | plugin_classes.clear(); 60 | } 61 | } 62 | 63 | } // namespace godot 64 | -------------------------------------------------------------------------------- /include/godot_cpp/core/math_defs.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* math_defs.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | namespace godot { 36 | 37 | #define CMP_EPSILON 0.00001 38 | #define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON) 39 | 40 | #define CMP_NORMALIZE_TOLERANCE 0.000001 41 | #define CMP_POINT_IN_PLANE_EPSILON 0.00001 42 | 43 | #define Math_SQRT12 0.7071067811865475244008443621048490 44 | #define Math_SQRT2 1.4142135623730950488016887242 45 | #define Math_LN2 0.6931471805599453094172321215 46 | #define Math_TAU 6.2831853071795864769252867666 47 | #define Math_PI 3.1415926535897932384626433833 48 | #define Math_E 2.7182818284590452353602874714 49 | 50 | #ifdef DEBUG_ENABLED 51 | #define MATH_CHECKS 52 | #endif 53 | 54 | //this epsilon is for values related to a unit size (scalar or vector len) 55 | #ifdef PRECISE_MATH_CHECKS 56 | #define UNIT_EPSILON 0.00001 57 | #else 58 | //tolerate some more floating point error normally 59 | #define UNIT_EPSILON 0.001 60 | #endif 61 | 62 | #define USEC_TO_SEC(m_usec) ((m_usec) / 1000000.0) 63 | 64 | /** 65 | * The "Real" type is an abstract type used for real numbers, such as 1.5, 66 | * in contrast to integer numbers. Precision can be controlled with the 67 | * presence or absence of the REAL_T_IS_DOUBLE define. 68 | */ 69 | #ifdef REAL_T_IS_DOUBLE 70 | typedef double real_t; 71 | #else 72 | typedef float real_t; 73 | #endif 74 | } // namespace godot 75 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Report a bug in the redot-cpp GDExtension/GDNative integration 3 | body: 4 | 5 | - type: markdown 6 | attributes: 7 | value: | 8 | - When reporting bugs, you'll make our life simpler (and the fix will come sooner) if you follow the guidelines in this template. 9 | - Write a descriptive issue title above. 10 | - The golden rule is to **always open *one* issue for *one* bug**. If you notice several bugs and want to report them, make sure to create one new issue for each of them. 11 | - Search [open](https://github.com/Redot-Engine/redot-cpp/issues) and [closed](https://github.com/Redot-Engine/redot-cpp/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported. If you don't find a relevant match or if you're unsure, don't hesitate to **open a new issue**. The bugsquad will handle it from there if it's a duplicate. 12 | - Verify that you are using a [supported Redot version](https://docs.Redot-Engine.org/en/latest/about/release_policy.html). 13 | 14 | - type: input 15 | attributes: 16 | label: Redot version 17 | description: > 18 | Specify the Git commit hash if using a development or non-official build. 19 | If you use a custom build, please test if your issue is reproducible in official builds too. 20 | placeholder: 3.3.stable, 4.0.dev (3041becc6) 21 | validations: 22 | required: true 23 | 24 | - type: input 25 | attributes: 26 | label: redot-cpp version 27 | description: > 28 | Specify the Git commit hash if using a development build. 29 | placeholder: 3.3.stable, 4.0.dev (3041becc6) 30 | validations: 31 | required: true 32 | 33 | - type: input 34 | attributes: 35 | label: System information 36 | description: | 37 | - Specify the OS version, and when relevant hardware information. 38 | - For issues that are likely OS-specific and/or graphics-related, please specify the CPU model and architecture. 39 | - **Bug reports not including the required information may be closed at the maintainers' discretion.** If in doubt, always include all the requested information; it's better to include too much information than not enough information. 40 | placeholder: Windows 10, Intel Core i5-7200U 41 | validations: 42 | required: true 43 | 44 | - type: textarea 45 | attributes: 46 | label: Issue description 47 | description: | 48 | Describe your issue briefly. What doesn't work, and how do you expect it to work instead? 49 | You can include images or videos with drag and drop, and format code blocks or logs with ``` tags. 50 | validations: 51 | required: true 52 | 53 | - type: textarea 54 | attributes: 55 | label: Steps to reproduce 56 | description: | 57 | List of steps or sample code that reproduces the issue. Having reproducible issues is a prerequisite for contributors to be able to solve them. 58 | If you include a minimal reproduction project below, you can detail how to use it here. 59 | validations: 60 | required: true 61 | 62 | - type: textarea 63 | attributes: 64 | label: Minimal reproduction project 65 | description: | 66 | - A small Redot project which reproduces the issue, with no unnecessary files included. Be sure to not include the `.godot` folder in the archive (but keep `project.godot`). 67 | - Required, unless the reproduction steps are trivial and don't require any project files to be followed. In this case, write "N/A" in the field. 68 | - Drag and drop a ZIP archive to upload it. **Do not select another field until the project is done uploading.** 69 | - **If you've been asked by a maintainer to upload a minimal reproduction project, you *must* do so within 7 days.** Otherwise, your bug report will be closed as it'll be considered too difficult to diagnose. 70 | validations: 71 | required: true 72 | -------------------------------------------------------------------------------- /src/variant/vector3i.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* vector3i.cpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #include 34 | 35 | #include 36 | #include 37 | 38 | namespace godot { 39 | 40 | Vector3i::Axis Vector3i::min_axis_index() const { 41 | return x < y ? (x < z ? Vector3i::AXIS_X : Vector3i::AXIS_Z) : (y < z ? Vector3i::AXIS_Y : Vector3i::AXIS_Z); 42 | } 43 | 44 | Vector3i::Axis Vector3i::max_axis_index() const { 45 | return x < y ? (y < z ? Vector3i::AXIS_Z : Vector3i::AXIS_Y) : (x < z ? Vector3i::AXIS_Z : Vector3i::AXIS_X); 46 | } 47 | 48 | Vector3i Vector3i::clamp(const Vector3i &p_min, const Vector3i &p_max) const { 49 | return Vector3i( 50 | CLAMP(x, p_min.x, p_max.x), 51 | CLAMP(y, p_min.y, p_max.y), 52 | CLAMP(z, p_min.z, p_max.z)); 53 | } 54 | 55 | Vector3i Vector3i::clampi(int32_t p_min, int32_t p_max) const { 56 | return Vector3i( 57 | CLAMP(x, p_min, p_max), 58 | CLAMP(y, p_min, p_max), 59 | CLAMP(z, p_min, p_max)); 60 | } 61 | 62 | Vector3i Vector3i::snapped(const Vector3i &p_step) const { 63 | return Vector3i( 64 | Math::snapped(x, p_step.x), 65 | Math::snapped(y, p_step.y), 66 | Math::snapped(z, p_step.z)); 67 | } 68 | 69 | Vector3i Vector3i::snappedi(int32_t p_step) const { 70 | return Vector3i( 71 | Math::snapped(x, p_step), 72 | Math::snapped(y, p_step), 73 | Math::snapped(z, p_step)); 74 | } 75 | 76 | Vector3i::operator String() const { 77 | return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ")"; 78 | } 79 | 80 | Vector3i::operator Vector3() const { 81 | return Vector3(x, y, z); 82 | } 83 | 84 | } // namespace godot 85 | -------------------------------------------------------------------------------- /tools/ios.py: -------------------------------------------------------------------------------- 1 | import codecs 2 | import os 3 | import subprocess 4 | import sys 5 | 6 | import common_compiler_flags 7 | from SCons.Variables import BoolVariable 8 | 9 | 10 | def has_ios_osxcross(): 11 | return "OSXCROSS_IOS" in os.environ 12 | 13 | 14 | def options(opts): 15 | opts.Add(BoolVariable("ios_simulator", "Target iOS Simulator", False)) 16 | opts.Add("ios_min_version", "Target minimum iphoneos/iphonesimulator version", "12.0") 17 | opts.Add( 18 | "IOS_TOOLCHAIN_PATH", 19 | "Path to iOS toolchain", 20 | "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain", 21 | ) 22 | opts.Add("IOS_SDK_PATH", "Path to the iOS SDK", "") 23 | 24 | if has_ios_osxcross(): 25 | opts.Add("ios_triple", "Triple for ios toolchain", "") 26 | 27 | 28 | def exists(env): 29 | return sys.platform == "darwin" or has_ios_osxcross() 30 | 31 | 32 | def generate(env): 33 | if env["arch"] not in ("universal", "arm64", "x86_64"): 34 | raise ValueError("Only universal, arm64, and x86_64 are supported on iOS. Exiting.") 35 | 36 | if env["ios_simulator"]: 37 | sdk_name = "iphonesimulator" 38 | env.Append(CCFLAGS=["-mios-simulator-version-min=" + env["ios_min_version"]]) 39 | else: 40 | sdk_name = "iphoneos" 41 | env.Append(CCFLAGS=["-miphoneos-version-min=" + env["ios_min_version"]]) 42 | 43 | if sys.platform == "darwin": 44 | if env["IOS_SDK_PATH"] == "": 45 | try: 46 | env["IOS_SDK_PATH"] = codecs.utf_8_decode( 47 | subprocess.check_output(["xcrun", "--sdk", sdk_name, "--show-sdk-path"]).strip() 48 | )[0] 49 | except (subprocess.CalledProcessError, OSError): 50 | raise ValueError( 51 | "Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name) 52 | ) 53 | 54 | compiler_path = env["IOS_TOOLCHAIN_PATH"] + "/usr/bin/" 55 | env["CC"] = compiler_path + "clang" 56 | env["CXX"] = compiler_path + "clang++" 57 | env["AR"] = compiler_path + "ar" 58 | env["RANLIB"] = compiler_path + "ranlib" 59 | env["SHLIBSUFFIX"] = ".dylib" 60 | env["ENV"]["PATH"] = env["IOS_TOOLCHAIN_PATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"] 61 | 62 | else: 63 | # OSXCross 64 | compiler_path = "$IOS_TOOLCHAIN_PATH/usr/bin/${ios_triple}" 65 | env["CC"] = compiler_path + "clang" 66 | env["CXX"] = compiler_path + "clang++" 67 | env["AR"] = compiler_path + "ar" 68 | env["RANLIB"] = compiler_path + "ranlib" 69 | env["SHLIBSUFFIX"] = ".dylib" 70 | 71 | env.Prepend( 72 | CPPPATH=[ 73 | "$IOS_SDK_PATH/usr/include", 74 | "$IOS_SDK_PATH/System/Library/Frameworks/AudioUnit.framework/Headers", 75 | ] 76 | ) 77 | 78 | env.Append(CCFLAGS=["-stdlib=libc++"]) 79 | 80 | binpath = os.path.join(env["IOS_TOOLCHAIN_PATH"], "usr", "bin") 81 | if binpath not in env["ENV"]["PATH"]: 82 | env.PrependENVPath("PATH", binpath) 83 | 84 | if env["arch"] == "universal": 85 | if env["ios_simulator"]: 86 | env.Append(LINKFLAGS=["-arch", "x86_64", "-arch", "arm64"]) 87 | env.Append(CCFLAGS=["-arch", "x86_64", "-arch", "arm64"]) 88 | else: 89 | env.Append(LINKFLAGS=["-arch", "arm64"]) 90 | env.Append(CCFLAGS=["-arch", "arm64"]) 91 | else: 92 | env.Append(LINKFLAGS=["-arch", env["arch"]]) 93 | env.Append(CCFLAGS=["-arch", env["arch"]]) 94 | 95 | env.Append(CCFLAGS=["-isysroot", env["IOS_SDK_PATH"]]) 96 | env.Append(LINKFLAGS=["-isysroot", env["IOS_SDK_PATH"], "-F" + env["IOS_SDK_PATH"]]) 97 | 98 | env.Append(CPPDEFINES=["IOS_ENABLED", "UNIX_ENABLED"]) 99 | 100 | # Refer to https://github.com/godotengine/godot/blob/master/platform/ios/detect.py: 101 | # Disable by default as it makes linking in Xcode very slow. 102 | if env["lto"] == "auto": 103 | env["lto"] = "none" 104 | 105 | common_compiler_flags.generate(env) 106 | -------------------------------------------------------------------------------- /src/classes/low_level.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* low_level.cpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include 39 | 40 | namespace godot { 41 | Error XMLParser::_open_buffer(const uint8_t *p_buffer, size_t p_size) { 42 | return (Error)internal::gdextension_interface_xml_parser_open_buffer(_owner, p_buffer, p_size); 43 | } 44 | 45 | uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const { 46 | return internal::gdextension_interface_file_access_get_buffer(_owner, p_dst, p_length); 47 | } 48 | 49 | void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) { 50 | internal::gdextension_interface_file_access_store_buffer(_owner, p_src, p_length); 51 | } 52 | 53 | WorkerThreadPool::TaskID WorkerThreadPool::add_native_task(void (*p_func)(void *), void *p_userdata, bool p_high_priority, const String &p_description) { 54 | return (TaskID)internal::gdextension_interface_worker_thread_pool_add_native_task(_owner, p_func, p_userdata, p_high_priority, (GDExtensionConstStringPtr)&p_description); 55 | } 56 | 57 | WorkerThreadPool::GroupID WorkerThreadPool::add_native_group_task(void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description) { 58 | return (GroupID)internal::gdextension_interface_worker_thread_pool_add_native_group_task(_owner, p_func, p_userdata, p_elements, p_tasks, p_high_priority, (GDExtensionConstStringPtr)&p_description); 59 | } 60 | 61 | uint8_t *Image::ptrw() { 62 | return internal::gdextension_interface_image_ptrw(_owner); 63 | } 64 | 65 | const uint8_t *Image::ptr() { 66 | return internal::gdextension_interface_image_ptr(_owner); 67 | } 68 | 69 | } // namespace godot 70 | -------------------------------------------------------------------------------- /include/godot_cpp/core/builtin_ptrcall.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* builtin_ptrcall.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | #include 36 | #include 37 | 38 | #include 39 | 40 | namespace godot { 41 | 42 | namespace internal { 43 | 44 | template 45 | O *_call_builtin_method_ptr_ret_obj(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, const Args &...args) { 46 | GodotObject *ret = nullptr; 47 | std::array call_args = { { (GDExtensionConstTypePtr)args... } }; 48 | method(base, call_args.data(), &ret, sizeof...(Args)); 49 | if (ret == nullptr) { 50 | return nullptr; 51 | } 52 | return reinterpret_cast(internal::get_object_instance_binding(ret)); 53 | } 54 | 55 | template 56 | void _call_builtin_constructor(const GDExtensionPtrConstructor constructor, GDExtensionTypePtr base, Args... args) { 57 | std::array call_args = { { (GDExtensionConstTypePtr)args... } }; 58 | constructor(base, call_args.data()); 59 | } 60 | 61 | template 62 | T _call_builtin_method_ptr_ret(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, Args... args) { 63 | T ret; 64 | std::array call_args = { { (GDExtensionConstTypePtr)args... } }; 65 | method(base, call_args.data(), &ret, sizeof...(Args)); 66 | return ret; 67 | } 68 | 69 | template 70 | void _call_builtin_method_ptr_no_ret(const GDExtensionPtrBuiltInMethod method, GDExtensionTypePtr base, Args... args) { 71 | std::array call_args = { { (GDExtensionConstTypePtr)args... } }; 72 | method(base, call_args.data(), nullptr, sizeof...(Args)); 73 | } 74 | 75 | template 76 | T _call_builtin_operator_ptr(const GDExtensionPtrOperatorEvaluator op, GDExtensionConstTypePtr left, GDExtensionConstTypePtr right) { 77 | T ret; 78 | op(left, right, &ret); 79 | return ret; 80 | } 81 | 82 | template 83 | T _call_builtin_ptr_getter(const GDExtensionPtrGetter getter, GDExtensionConstTypePtr base) { 84 | T ret; 85 | getter(base, &ret); 86 | return ret; 87 | } 88 | 89 | } // namespace internal 90 | 91 | } // namespace godot 92 | -------------------------------------------------------------------------------- /src/variant/vector4i.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* vector4i.cpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #include 34 | 35 | #include 36 | #include 37 | 38 | namespace godot { 39 | 40 | Vector4i::Axis Vector4i::min_axis_index() const { 41 | uint32_t min_index = 0; 42 | int32_t min_value = x; 43 | for (uint32_t i = 1; i < 4; i++) { 44 | if (operator[](i) <= min_value) { 45 | min_index = i; 46 | min_value = operator[](i); 47 | } 48 | } 49 | return Vector4i::Axis(min_index); 50 | } 51 | 52 | Vector4i::Axis Vector4i::max_axis_index() const { 53 | uint32_t max_index = 0; 54 | int32_t max_value = x; 55 | for (uint32_t i = 1; i < 4; i++) { 56 | if (operator[](i) > max_value) { 57 | max_index = i; 58 | max_value = operator[](i); 59 | } 60 | } 61 | return Vector4i::Axis(max_index); 62 | } 63 | 64 | Vector4i Vector4i::clamp(const Vector4i &p_min, const Vector4i &p_max) const { 65 | return Vector4i( 66 | CLAMP(x, p_min.x, p_max.x), 67 | CLAMP(y, p_min.y, p_max.y), 68 | CLAMP(z, p_min.z, p_max.z), 69 | CLAMP(w, p_min.w, p_max.w)); 70 | } 71 | 72 | Vector4i Vector4i::clampi(int32_t p_min, int32_t p_max) const { 73 | return Vector4i( 74 | CLAMP(x, p_min, p_max), 75 | CLAMP(y, p_min, p_max), 76 | CLAMP(z, p_min, p_max), 77 | CLAMP(w, p_min, p_max)); 78 | } 79 | 80 | Vector4i Vector4i::snapped(const Vector4i &p_step) const { 81 | return Vector4i( 82 | Math::snapped(x, p_step.x), 83 | Math::snapped(y, p_step.y), 84 | Math::snapped(z, p_step.z), 85 | Math::snapped(w, p_step.w)); 86 | } 87 | 88 | Vector4i Vector4i::snappedi(int32_t p_step) const { 89 | return Vector4i( 90 | Math::snapped(x, p_step), 91 | Math::snapped(y, p_step), 92 | Math::snapped(z, p_step), 93 | Math::snapped(w, p_step)); 94 | } 95 | 96 | Vector4i::operator String() const { 97 | return "(" + itos(x) + ", " + itos(y) + ", " + itos(z) + ", " + itos(w) + ")"; 98 | } 99 | 100 | Vector4i::operator Vector4() const { 101 | return Vector4(x, y, z, w); 102 | } 103 | 104 | Vector4i::Vector4i(const Vector4 &p_vec4) { 105 | x = (int32_t)p_vec4.x; 106 | y = (int32_t)p_vec4.y; 107 | z = (int32_t)p_vec4.z; 108 | w = (int32_t)p_vec4.w; 109 | } 110 | 111 | static_assert(sizeof(Vector4i) == 4 * sizeof(int32_t)); 112 | 113 | } // namespace godot 114 | -------------------------------------------------------------------------------- /include/godot_cpp/templates/pair.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* pair.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | #include 36 | 37 | namespace godot { 38 | 39 | template 40 | struct Pair { 41 | F first; 42 | S second; 43 | 44 | Pair() : 45 | first(), 46 | second() { 47 | } 48 | 49 | Pair(F p_first, const S &p_second) : 50 | first(p_first), 51 | second(p_second) { 52 | } 53 | }; 54 | 55 | template 56 | bool operator==(const Pair &pair, const Pair &other) { 57 | return (pair.first == other.first) && (pair.second == other.second); 58 | } 59 | 60 | template 61 | bool operator!=(const Pair &pair, const Pair &other) { 62 | return (pair.first != other.first) || (pair.second != other.second); 63 | } 64 | 65 | template 66 | struct PairSort { 67 | bool operator()(const Pair &A, const Pair &B) const { 68 | if (A.first != B.first) { 69 | return A.first < B.first; 70 | } 71 | return A.second < B.second; 72 | } 73 | }; 74 | 75 | template 76 | struct PairHash { 77 | static uint32_t hash(const Pair &P) { 78 | uint64_t h1 = HashMapHasherDefault::hash(P.first); 79 | uint64_t h2 = HashMapHasherDefault::hash(P.second); 80 | return hash_one_uint64((h1 << 32) | h2); 81 | } 82 | }; 83 | 84 | template 85 | struct KeyValue { 86 | const K key; 87 | V value; 88 | 89 | void operator=(const KeyValue &p_kv) = delete; 90 | _FORCE_INLINE_ KeyValue(const KeyValue &p_kv) : 91 | key(p_kv.key), 92 | value(p_kv.value) { 93 | } 94 | _FORCE_INLINE_ KeyValue(const K &p_key, const V &p_value) : 95 | key(p_key), 96 | value(p_value) { 97 | } 98 | }; 99 | 100 | template 101 | bool operator==(const KeyValue &pair, const KeyValue &other) { 102 | return (pair.key == other.key) && (pair.value == other.value); 103 | } 104 | 105 | template 106 | bool operator!=(const KeyValue &pair, const KeyValue &other) { 107 | return (pair.key != other.key) || (pair.value != other.value); 108 | } 109 | 110 | template 111 | struct KeyValueSort { 112 | bool operator()(const KeyValue &A, const KeyValue &B) const { 113 | return A.key < B.key; 114 | } 115 | }; 116 | 117 | } // namespace godot 118 | -------------------------------------------------------------------------------- /tools/android.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | import common_compiler_flags 5 | import my_spawn 6 | 7 | 8 | def options(opts): 9 | opts.Add( 10 | "android_api_level", 11 | "Target Android API level", 12 | "21", 13 | ) 14 | opts.Add( 15 | "ANDROID_HOME", 16 | "Path to your Android SDK installation. By default, uses ANDROID_HOME from your defined environment variables.", 17 | os.environ.get("ANDROID_HOME", os.environ.get("ANDROID_SDK_ROOT")), 18 | ) 19 | 20 | 21 | def exists(env): 22 | return get_android_ndk_root(env) is not None 23 | 24 | 25 | # This must be kept in sync with the value in https://github.com/godotengine/godot/blob/master/platform/android/detect.py#L58. 26 | def get_ndk_version(): 27 | return "23.2.8568313" 28 | 29 | 30 | def get_android_ndk_root(env): 31 | if env["ANDROID_HOME"]: 32 | return env["ANDROID_HOME"] + "/ndk/" + get_ndk_version() 33 | else: 34 | return os.environ.get("ANDROID_NDK_ROOT") 35 | 36 | 37 | def generate(env): 38 | if get_android_ndk_root(env) is None: 39 | raise ValueError( 40 | "To build for Android, the path to the NDK must be defined. Please set ANDROID_HOME to the root folder of your Android SDK installation." 41 | ) 42 | 43 | if env["arch"] not in ("arm64", "x86_64", "arm32", "x86_32"): 44 | print("Only arm64, x86_64, arm32, and x86_32 are supported on Android. Exiting.") 45 | env.Exit(1) 46 | 47 | if sys.platform == "win32" or sys.platform == "msys": 48 | my_spawn.configure(env) 49 | 50 | # Validate API level 51 | if int(env["android_api_level"]) < 21: 52 | print("WARNING: minimum supported Android target api is 21. Forcing target api 21.") 53 | env["android_api_level"] = "21" 54 | 55 | # Setup toolchain 56 | toolchain = get_android_ndk_root(env) + "/toolchains/llvm/prebuilt/" 57 | if sys.platform == "win32" or sys.platform == "msys": 58 | toolchain += "windows" 59 | import platform as pltfm 60 | 61 | if pltfm.machine().endswith("64"): 62 | toolchain += "-x86_64" 63 | elif sys.platform.startswith("linux"): 64 | toolchain += "linux-x86_64" 65 | elif sys.platform == "darwin": 66 | toolchain += "darwin-x86_64" 67 | env.Append(LINKFLAGS=["-shared"]) 68 | 69 | if not os.path.exists(toolchain): 70 | print("ERROR: Could not find NDK toolchain at " + toolchain + ".") 71 | print("Make sure NDK version " + get_ndk_version() + " is installed.") 72 | env.Exit(1) 73 | 74 | env.PrependENVPath("PATH", toolchain + "/bin") # This does nothing half of the time, but we'll put it here anyways 75 | 76 | # Get architecture info 77 | arch_info_table = { 78 | "arm32": { 79 | "march": "armv7-a", 80 | "target": "armv7a-linux-androideabi", 81 | "compiler_path": "armv7a-linux-androideabi", 82 | "ccflags": ["-mfpu=neon"], 83 | }, 84 | "arm64": { 85 | "march": "armv8-a", 86 | "target": "aarch64-linux-android", 87 | "compiler_path": "aarch64-linux-android", 88 | "ccflags": [], 89 | }, 90 | "x86_32": { 91 | "march": "i686", 92 | "target": "i686-linux-android", 93 | "compiler_path": "i686-linux-android", 94 | "ccflags": ["-mstackrealign"], 95 | }, 96 | "x86_64": { 97 | "march": "x86-64", 98 | "target": "x86_64-linux-android", 99 | "compiler_path": "x86_64-linux-android", 100 | "ccflags": [], 101 | }, 102 | } 103 | arch_info = arch_info_table[env["arch"]] 104 | 105 | # Setup tools 106 | env["CC"] = toolchain + "/bin/clang" 107 | env["CXX"] = toolchain + "/bin/clang++" 108 | env["LINK"] = toolchain + "/bin/clang++" 109 | env["AR"] = toolchain + "/bin/llvm-ar" 110 | env["AS"] = toolchain + "/bin/llvm-as" 111 | env["STRIP"] = toolchain + "/bin/llvm-strip" 112 | env["RANLIB"] = toolchain + "/bin/llvm-ranlib" 113 | env["SHLIBSUFFIX"] = ".so" 114 | 115 | env.Append( 116 | CCFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"], "-fPIC"] 117 | ) 118 | env.Append(CCFLAGS=arch_info["ccflags"]) 119 | env.Append(LINKFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"]]) 120 | 121 | env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED"]) 122 | 123 | # Refer to https://github.com/godotengine/godot/blob/master/platform/android/detect.py 124 | # LTO benefits for Android (size, performance) haven't been clearly established yet. 125 | if env["lto"] == "auto": 126 | env["lto"] = "none" 127 | 128 | common_compiler_flags.generate(env) 129 | -------------------------------------------------------------------------------- /misc/scripts/copyright_headers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import sys 6 | 7 | header = """\ 8 | /**************************************************************************/ 9 | /* $filename */ 10 | /**************************************************************************/ 11 | /* This file is part of: */ 12 | /* REDOT ENGINE */ 13 | /* https://redotengine.org */ 14 | /**************************************************************************/ 15 | /* Copyright (c) 2024-present Redot Engine contributors */ 16 | /* (see REDOT_AUTHORS.md) */ 17 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 18 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 19 | /* */ 20 | /* Permission is hereby granted, free of charge, to any person obtaining */ 21 | /* a copy of this software and associated documentation files (the */ 22 | /* "Software"), to deal in the Software without restriction, including */ 23 | /* without limitation the rights to use, copy, modify, merge, publish, */ 24 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 25 | /* permit persons to whom the Software is furnished to do so, subject to */ 26 | /* the following conditions: */ 27 | /* */ 28 | /* The above copyright notice and this permission notice shall be */ 29 | /* included in all copies or substantial portions of the Software. */ 30 | /* */ 31 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 32 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 33 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 34 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 35 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 36 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 37 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 38 | /**************************************************************************/ 39 | """ 40 | 41 | if len(sys.argv) < 2: 42 | print("Invalid usage of copyright_headers.py, it should be called with a path to one or multiple files.") 43 | sys.exit(1) 44 | 45 | for f in sys.argv[1:]: 46 | fname = f 47 | 48 | # Handle replacing $filename with actual filename and keep alignment 49 | fsingle = os.path.basename(fname.strip()) 50 | rep_fl = "$filename" 51 | rep_fi = fsingle 52 | len_fl = len(rep_fl) 53 | len_fi = len(rep_fi) 54 | # Pad with spaces to keep alignment 55 | if len_fi < len_fl: 56 | for x in range(len_fl - len_fi): 57 | rep_fi += " " 58 | elif len_fl < len_fi: 59 | for x in range(len_fi - len_fl): 60 | rep_fl += " " 61 | if header.find(rep_fl) != -1: 62 | text = header.replace(rep_fl, rep_fi) 63 | else: 64 | text = header.replace("$filename", fsingle) 65 | text += "\n" 66 | 67 | # We now have the proper header, so we want to ignore the one in the original file 68 | # and potentially empty lines and badly formatted lines, while keeping comments that 69 | # come after the header, and then keep everything non-header unchanged. 70 | # To do so, we skip empty lines that may be at the top in a first pass. 71 | # In a second pass, we skip all consecutive comment lines starting with "/*", 72 | # then we can append the rest (step 2). 73 | 74 | with open(fname.strip(), "r", encoding="utf-8") as fileread: 75 | line = fileread.readline() 76 | header_done = False 77 | 78 | while line.strip() == "" and line != "": # Skip empty lines at the top 79 | line = fileread.readline() 80 | 81 | if line.find("/**********") == -1: # Redot header starts this way 82 | # Maybe starting with a non-Redot comment, abort header magic 83 | header_done = True 84 | 85 | while not header_done: # Handle header now 86 | if line.find("/*") != 0: # No more starting with a comment 87 | header_done = True 88 | if line.strip() != "": 89 | text += line 90 | line = fileread.readline() 91 | 92 | while line != "": # Dump everything until EOF 93 | text += line 94 | line = fileread.readline() 95 | 96 | # Write 97 | with open(fname.strip(), "w", encoding="utf-8", newline="\n") as filewrite: 98 | filewrite.write(text) 99 | -------------------------------------------------------------------------------- /cmake/windows.cmake: -------------------------------------------------------------------------------- 1 | #[=======================================================================[.rst: 2 | Windows 3 | ------- 4 | This file contains functions for options and configuration for targeting the 5 | Windows platform 6 | 7 | Because this file is included into the top level CMakelists.txt before the 8 | project directive, it means that 9 | 10 | * ``CMAKE_CURRENT_SOURCE_DIR`` is the location of godot-cpp's CMakeLists.txt 11 | * ``CMAKE_SOURCE_DIR`` is the location where any prior ``project(...)`` 12 | directive was 13 | 14 | MSVC Runtime Selection 15 | ---------------------- 16 | 17 | There are two main ways to set the msvc runtime library; 18 | Using ``target_compile_options()`` to add the flags 19 | or using the ``CMAKE_MSVC_RUNTIME_LIBRARY`` property_ abstraction, introduced 20 | in CMake version 3.15 with the policy CMP0091_ to remove the flags from 21 | ``CMAKE__FLAGS_``. 22 | 23 | Default: ``CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$:Debug>DLL"`` 24 | 25 | This initializes each target's ``MSVC_RUNTIME_LIBRARY`` property at the time of 26 | target creation. 27 | 28 | it is stated in the msvc_ documentation that: "All modules passed to a given 29 | invocation of the linker must have been compiled with the same runtime library 30 | compiler option (/MD, /MT, /LD)." 31 | 32 | This creates a conundrum for us, the ``CMAKE_MSVC_RUNTIME_LIBRARY`` needs to be 33 | correct at the time the target is created, but we have no control over the 34 | consumers CMake scripts, and the per-target ``MSVC_RUNTIME_LIBRARY`` property 35 | is not transient. 36 | 37 | It has been raised that not using ``CMAKE_MSVC_RUNTIME_LIBRARY`` can also cause 38 | issues_ when a dependency( independent to godot-cpp ) that doesn't set any 39 | runtime flags, which relies purely on the ``CMAKE_MSVC_RUNTIME_LIBRARY`` 40 | variable will very likely not have the correct msvc runtime flags set. 41 | 42 | So we'll set ``CMAKE_MSVC_RUNTIME_LIBRARY`` as CACHE STRING so that it will be 43 | available for consumer target definitions, but also be able to be overridden if 44 | needed. 45 | 46 | Additionally we message consumers notifying them and pointing to this 47 | documentation. 48 | 49 | .. _CMP0091:https://cmake.org/cmake/help/latest/policy/CMP0091.html 50 | .. _property:https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html 51 | .. https://discourse.cmake.org/t/mt-staticrelease-doesnt-match-value-md-dynamicrelease/5428/4 52 | .. _msvc: https://learn.microsoft.com/en-us/cpp/build/reference/md-mt-ld-use-run-time-library 53 | .. _issues: https://github.com/godotengine/godot-cpp/issues/1699 54 | 55 | ]=======================================================================] 56 | 57 | #[============================[ Windows Options ]============================] 58 | function(windows_options) 59 | #[[ Options from SCons 60 | 61 | TODO silence_msvc: Silence MSVC's cl/link stdout bloat, redirecting errors to stderr 62 | Default: True 63 | 64 | These three options will not implemented as compiler selection is managed 65 | by CMake toolchain files. Look to doc/cmake.rst for examples. 66 | use_mingw: Use the MinGW compiler instead of MSVC - only effective on Windows 67 | use_llvm: Use the LLVM compiler (MVSC or MinGW depending on the use_mingw flag 68 | mingw_prefix: MinGW prefix 69 | ]] 70 | 71 | option(GODOTCPP_USE_STATIC_CPP "Link MinGW/MSVC C++ runtime libraries statically" ON) 72 | option(GODOTCPP_DEBUG_CRT "Compile with MSVC's debug CRT (/MDd)" OFF) 73 | 74 | message( 75 | STATUS 76 | "If not already cached, setting CMAKE_MSVC_RUNTIME_LIBRARY.\n" 77 | "\tFor more information please read godot-cpp/cmake/windows.cmake" 78 | ) 79 | 80 | set(CMAKE_MSVC_RUNTIME_LIBRARY 81 | "MultiThreaded$,DebugDLL,$<$>:DLL>>" 82 | CACHE STRING 83 | "Select the MSVC runtime library for use by compilers targeting the MSVC ABI." 84 | ) 85 | endfunction() 86 | 87 | #[===========================[ Target Generation ]===========================] 88 | function(windows_generate) 89 | set(STATIC_CPP "$") 90 | 91 | set_target_properties(godot-cpp PROPERTIES PDB_OUTPUT_DIRECTORY "$<1:${CMAKE_SOURCE_DIR}/bin>") 92 | 93 | target_compile_definitions( 94 | godot-cpp 95 | PUBLIC WINDOWS_ENABLED $<${IS_MSVC}: TYPED_METHOD_BIND NOMINMAX > 96 | ) 97 | 98 | # gersemi: off 99 | target_link_options( 100 | godot-cpp 101 | PUBLIC 102 | $<${NOT_MSVC}: 103 | -Wl,--no-undefined 104 | $<${STATIC_CPP}: 105 | -static 106 | -static-libgcc 107 | -static-libstdc++ 108 | > 109 | > 110 | 111 | $<${IS_CLANG}:-lstdc++> 112 | ) 113 | # gersemi: on 114 | 115 | common_compiler_flags() 116 | endfunction() 117 | -------------------------------------------------------------------------------- /include/godot_cpp/core/engine_ptrcall.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* engine_ptrcall.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #include 42 | 43 | namespace godot { 44 | 45 | namespace internal { 46 | 47 | template 48 | O *_call_native_mb_ret_obj(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) { 49 | GodotObject *ret = nullptr; 50 | std::array mb_args = { { (GDExtensionConstTypePtr)args... } }; 51 | internal::gdextension_interface_object_method_bind_ptrcall(mb, instance, mb_args.data(), &ret); 52 | if (ret == nullptr) { 53 | return nullptr; 54 | } 55 | return reinterpret_cast(internal::get_object_instance_binding(ret)); 56 | } 57 | 58 | template 59 | R _call_native_mb_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) { 60 | typename PtrToArg::EncodeT ret; 61 | std::array mb_args = { { (GDExtensionConstTypePtr)args... } }; 62 | internal::gdextension_interface_object_method_bind_ptrcall(mb, instance, mb_args.data(), &ret); 63 | return static_cast(ret); 64 | } 65 | 66 | template 67 | void _call_native_mb_no_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) { 68 | std::array mb_args = { { (GDExtensionConstTypePtr)args... } }; 69 | internal::gdextension_interface_object_method_bind_ptrcall(mb, instance, mb_args.data(), nullptr); 70 | } 71 | 72 | template 73 | R _call_utility_ret(GDExtensionPtrUtilityFunction func, const Args &...args) { 74 | typename PtrToArg::EncodeT ret; 75 | std::array mb_args = { { (GDExtensionConstTypePtr)args... } }; 76 | func(&ret, mb_args.data(), mb_args.size()); 77 | return static_cast(ret); 78 | } 79 | 80 | template 81 | Object *_call_utility_ret_obj(const GDExtensionPtrUtilityFunction func, const Args &...args) { 82 | GodotObject *ret = nullptr; 83 | std::array mb_args = { { (GDExtensionConstTypePtr)args... } }; 84 | func(&ret, mb_args.data(), mb_args.size()); 85 | return (Object *)internal::get_object_instance_binding(ret); 86 | } 87 | 88 | template 89 | void _call_utility_no_ret(const GDExtensionPtrUtilityFunction func, const Args &...args) { 90 | std::array mb_args = { { (GDExtensionConstTypePtr)args... } }; 91 | func(nullptr, mb_args.data(), mb_args.size()); 92 | } 93 | 94 | } // namespace internal 95 | 96 | } // namespace godot 97 | -------------------------------------------------------------------------------- /include/godot_cpp/templates/vset.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* vset.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | #include 36 | 37 | namespace godot { 38 | 39 | template 40 | class VSet { 41 | Vector _data; 42 | 43 | _FORCE_INLINE_ int _find(const T &p_val, bool &r_exact) const { 44 | r_exact = false; 45 | if (_data.is_empty()) { 46 | return 0; 47 | } 48 | 49 | int low = 0; 50 | int high = _data.size() - 1; 51 | const T *a = &_data[0]; 52 | int middle = 0; 53 | 54 | #ifdef DEBUG_ENABLED 55 | if (low > high) { 56 | ERR_PRINT("low > high, this may be a bug"); 57 | } 58 | #endif 59 | 60 | while (low <= high) { 61 | middle = (low + high) / 2; 62 | 63 | if (p_val < a[middle]) { 64 | high = middle - 1; //search low end of array 65 | } else if (a[middle] < p_val) { 66 | low = middle + 1; //search high end of array 67 | } else { 68 | r_exact = true; 69 | return middle; 70 | } 71 | } 72 | 73 | //return the position where this would be inserted 74 | if (a[middle] < p_val) { 75 | middle++; 76 | } 77 | return middle; 78 | } 79 | 80 | _FORCE_INLINE_ int _find_exact(const T &p_val) const { 81 | if (_data.is_empty()) { 82 | return -1; 83 | } 84 | 85 | int low = 0; 86 | int high = _data.size() - 1; 87 | int middle; 88 | const T *a = &_data[0]; 89 | 90 | while (low <= high) { 91 | middle = (low + high) / 2; 92 | 93 | if (p_val < a[middle]) { 94 | high = middle - 1; //search low end of array 95 | } else if (a[middle] < p_val) { 96 | low = middle + 1; //search high end of array 97 | } else { 98 | return middle; 99 | } 100 | } 101 | 102 | return -1; 103 | } 104 | 105 | public: 106 | void insert(const T &p_val) { 107 | bool exact; 108 | int pos = _find(p_val, exact); 109 | if (exact) { 110 | return; 111 | } 112 | _data.insert(pos, p_val); 113 | } 114 | 115 | bool has(const T &p_val) const { 116 | return _find_exact(p_val) != -1; 117 | } 118 | 119 | void erase(const T &p_val) { 120 | int pos = _find_exact(p_val); 121 | if (pos < 0) { 122 | return; 123 | } 124 | _data.remove_at(pos); 125 | } 126 | 127 | int find(const T &p_val) const { 128 | return _find_exact(p_val); 129 | } 130 | 131 | _FORCE_INLINE_ bool is_empty() const { return _data.is_empty(); } 132 | 133 | _FORCE_INLINE_ int size() const { return _data.size(); } 134 | 135 | inline T &operator[](int p_index) { 136 | return _data.write[p_index]; 137 | } 138 | 139 | inline const T &operator[](int p_index) const { 140 | return _data[p_index]; 141 | } 142 | 143 | _FORCE_INLINE_ VSet() {} 144 | _FORCE_INLINE_ VSet(std::initializer_list p_init) : 145 | _data(p_init) {} 146 | }; 147 | 148 | } // namespace godot 149 | -------------------------------------------------------------------------------- /tools/common_compiler_flags.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | 4 | 5 | def using_clang(env): 6 | return "clang" in os.path.basename(env["CC"]) 7 | 8 | 9 | def is_vanilla_clang(env): 10 | if not using_clang(env): 11 | return False 12 | try: 13 | version = subprocess.check_output([env.subst(env["CXX"]), "--version"]).strip().decode("utf-8") 14 | except (subprocess.CalledProcessError, OSError): 15 | print("Couldn't parse CXX environment variable to infer compiler version.") 16 | return False 17 | return not version.startswith("Apple") 18 | 19 | 20 | def exists(env): 21 | return True 22 | 23 | 24 | def generate(env): 25 | assert env["lto"] in ["thin", "full", "none"], "Unrecognized lto: {}".format(env["lto"]) 26 | if env["lto"] != "none": 27 | print("Using LTO: " + env["lto"]) 28 | 29 | # Require C++17 30 | if env.get("is_msvc", False): 31 | env.Append(CXXFLAGS=["/std:c++17"]) 32 | else: 33 | env.Append(CXXFLAGS=["-std=c++17"]) 34 | 35 | # Disable exception handling. Godot doesn't use exceptions anywhere, and this 36 | # saves around 20% of binary size and very significant build time. 37 | if env["disable_exceptions"]: 38 | if env.get("is_msvc", False): 39 | env.Append(CPPDEFINES=[("_HAS_EXCEPTIONS", 0)]) 40 | else: 41 | env.Append(CXXFLAGS=["-fno-exceptions"]) 42 | elif env.get("is_msvc", False): 43 | env.Append(CXXFLAGS=["/EHsc"]) 44 | 45 | if not env.get("is_msvc", False): 46 | if env["symbols_visibility"] == "visible": 47 | env.Append(CCFLAGS=["-fvisibility=default"]) 48 | env.Append(LINKFLAGS=["-fvisibility=default"]) 49 | elif env["symbols_visibility"] == "hidden": 50 | env.Append(CCFLAGS=["-fvisibility=hidden"]) 51 | env.Append(LINKFLAGS=["-fvisibility=hidden"]) 52 | 53 | # Set optimize and debug_symbols flags. 54 | # "custom" means do nothing and let users set their own optimization flags. 55 | if env.get("is_msvc", False): 56 | if env["debug_symbols"]: 57 | env.Append(CCFLAGS=["/Zi", "/FS"]) 58 | env.Append(LINKFLAGS=["/DEBUG:FULL"]) 59 | 60 | if env["optimize"] == "speed": 61 | env.Append(CCFLAGS=["/O2"]) 62 | env.Append(LINKFLAGS=["/OPT:REF"]) 63 | elif env["optimize"] == "speed_trace": 64 | env.Append(CCFLAGS=["/O2"]) 65 | env.Append(LINKFLAGS=["/OPT:REF", "/OPT:NOICF"]) 66 | elif env["optimize"] == "size": 67 | env.Append(CCFLAGS=["/O1"]) 68 | env.Append(LINKFLAGS=["/OPT:REF"]) 69 | elif env["optimize"] == "debug" or env["optimize"] == "none": 70 | env.Append(CCFLAGS=["/Od"]) 71 | 72 | if env["lto"] == "thin": 73 | if not env["use_llvm"]: 74 | print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.") 75 | env.Exit(255) 76 | 77 | env.Append(CCFLAGS=["-flto=thin"]) 78 | env.Append(LINKFLAGS=["-flto=thin"]) 79 | elif env["lto"] == "full": 80 | if env["use_llvm"]: 81 | env.Append(CCFLAGS=["-flto"]) 82 | env.Append(LINKFLAGS=["-flto"]) 83 | else: 84 | env.AppendUnique(CCFLAGS=["/GL"]) 85 | env.AppendUnique(ARFLAGS=["/LTCG"]) 86 | env.AppendUnique(LINKFLAGS=["/LTCG"]) 87 | else: 88 | if env["debug_symbols"]: 89 | # Adding dwarf-4 explicitly makes stacktraces work with clang builds, 90 | # otherwise addr2line doesn't understand them. 91 | env.Append(CCFLAGS=["-gdwarf-4"]) 92 | if env.dev_build: 93 | env.Append(CCFLAGS=["-g3"]) 94 | else: 95 | env.Append(CCFLAGS=["-g2"]) 96 | else: 97 | if using_clang(env) and not is_vanilla_clang(env) and not env["use_mingw"]: 98 | # Apple Clang, its linker doesn't like -s. 99 | env.Append(LINKFLAGS=["-Wl,-S", "-Wl,-x", "-Wl,-dead_strip"]) 100 | else: 101 | env.Append(LINKFLAGS=["-s"]) 102 | 103 | if env["optimize"] == "speed": 104 | env.Append(CCFLAGS=["-O3"]) 105 | # `-O2` is friendlier to debuggers than `-O3`, leading to better crash backtraces. 106 | elif env["optimize"] == "speed_trace": 107 | env.Append(CCFLAGS=["-O2"]) 108 | elif env["optimize"] == "size": 109 | env.Append(CCFLAGS=["-Os"]) 110 | elif env["optimize"] == "debug": 111 | env.Append(CCFLAGS=["-Og"]) 112 | elif env["optimize"] == "none": 113 | env.Append(CCFLAGS=["-O0"]) 114 | 115 | if env["lto"] == "thin": 116 | if (env["platform"] == "windows" or env["platform"] == "linux") and not env["use_llvm"]: 117 | print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.") 118 | env.Exit(255) 119 | env.Append(CCFLAGS=["-flto=thin"]) 120 | env.Append(LINKFLAGS=["-flto=thin"]) 121 | elif env["lto"] == "full": 122 | env.Append(CCFLAGS=["-flto"]) 123 | env.Append(LINKFLAGS=["-flto"]) 124 | -------------------------------------------------------------------------------- /src/core/method_bind.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* method_bind.cpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #include 34 | 35 | namespace godot { 36 | 37 | StringName MethodBind::get_name() const { 38 | return name; 39 | } 40 | 41 | void MethodBind::set_name(const StringName &p_name) { 42 | name = p_name; 43 | } 44 | 45 | void MethodBind::set_argument_count(int p_count) { 46 | argument_count = p_count; 47 | } 48 | 49 | void MethodBind::set_const(bool p_const) { 50 | _is_const = p_const; 51 | } 52 | 53 | void MethodBind::set_return(bool p_return) { 54 | _has_return = p_return; 55 | } 56 | 57 | void MethodBind::set_static(bool p_static) { 58 | _static = p_static; 59 | } 60 | 61 | void MethodBind::set_vararg(bool p_vararg) { 62 | _vararg = p_vararg; 63 | } 64 | 65 | void MethodBind::set_argument_names(const std::vector &p_names) { 66 | argument_names = p_names; 67 | } 68 | 69 | std::vector MethodBind::get_argument_names() const { 70 | return argument_names; 71 | } 72 | 73 | void MethodBind::generate_argument_types(int p_count) { 74 | set_argument_count(p_count); 75 | 76 | if (argument_types != nullptr) { 77 | memdelete_arr(argument_types); 78 | } 79 | 80 | argument_types = memnew_arr(GDExtensionVariantType, p_count + 1); 81 | 82 | // -1 means return type. 83 | for (int i = -1; i < p_count; i++) { 84 | argument_types[i + 1] = gen_argument_type(i); 85 | } 86 | } 87 | 88 | PropertyInfo MethodBind::get_argument_info(int p_argument) const { 89 | PropertyInfo info = gen_argument_type_info(p_argument); 90 | if (p_argument >= 0) { 91 | info.name = p_argument < (int)argument_names.size() ? argument_names[p_argument] : ""; 92 | } 93 | return info; 94 | } 95 | 96 | void MethodBind::bind_call(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error) { 97 | const MethodBind *bind = reinterpret_cast(p_method_userdata); 98 | Variant ret = bind->call(p_instance, p_args, p_argument_count, *r_error); 99 | // This assumes the return value is an empty Variant, so it doesn't need to call the destructor first. 100 | // Since only GDExtensionMethodBind calls this from the Godot side, it should always be the case. 101 | internal::gdextension_interface_variant_new_copy(r_return, ret._native_ptr()); 102 | } 103 | 104 | void MethodBind::bind_ptrcall(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return) { 105 | const MethodBind *bind = reinterpret_cast(p_method_userdata); 106 | bind->ptrcall(p_instance, p_args, r_return); 107 | } 108 | 109 | MethodBind::~MethodBind() { 110 | if (argument_types) { 111 | memdelete_arr(argument_types); 112 | } 113 | } 114 | 115 | } // namespace godot 116 | -------------------------------------------------------------------------------- /src/core/memory.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* memory.cpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #include 34 | 35 | #include 36 | 37 | namespace godot { 38 | 39 | void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) { 40 | #ifdef DEBUG_ENABLED 41 | bool prepad = false; // Already pre paded in the engine. 42 | #else 43 | bool prepad = p_pad_align; 44 | #endif 45 | 46 | void *mem = internal::gdextension_interface_mem_alloc(p_bytes + (prepad ? DATA_OFFSET : 0)); 47 | ERR_FAIL_NULL_V(mem, nullptr); 48 | 49 | if (prepad) { 50 | uint8_t *s8 = (uint8_t *)mem; 51 | return s8 + DATA_OFFSET; 52 | } else { 53 | return mem; 54 | } 55 | } 56 | 57 | void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) { 58 | if (p_memory == nullptr) { 59 | return alloc_static(p_bytes, p_pad_align); 60 | } else if (p_bytes == 0) { 61 | free_static(p_memory, p_pad_align); 62 | return nullptr; 63 | } 64 | 65 | uint8_t *mem = (uint8_t *)p_memory; 66 | 67 | #ifdef DEBUG_ENABLED 68 | bool prepad = false; // Already pre paded in the engine. 69 | #else 70 | bool prepad = p_pad_align; 71 | #endif 72 | 73 | if (prepad) { 74 | mem -= DATA_OFFSET; 75 | mem = (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes + DATA_OFFSET); 76 | ERR_FAIL_NULL_V(mem, nullptr); 77 | return mem + DATA_OFFSET; 78 | } else { 79 | return (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes); 80 | } 81 | } 82 | 83 | void Memory::free_static(void *p_ptr, bool p_pad_align) { 84 | uint8_t *mem = (uint8_t *)p_ptr; 85 | 86 | #ifdef DEBUG_ENABLED 87 | bool prepad = false; // Already pre paded in the engine. 88 | #else 89 | bool prepad = p_pad_align; 90 | #endif 91 | 92 | if (prepad) { 93 | mem -= DATA_OFFSET; 94 | } 95 | internal::gdextension_interface_mem_free(mem); 96 | } 97 | 98 | _GlobalNil::_GlobalNil() { 99 | left = this; 100 | right = this; 101 | parent = this; 102 | } 103 | 104 | _GlobalNil _GlobalNilClass::_nil; 105 | 106 | } // namespace godot 107 | 108 | // p_dummy argument is added to avoid conflicts with the engine functions when both engine and GDExtension are built as a static library on iOS. 109 | void *operator new(size_t p_size, const char *p_dummy, const char *p_description) { 110 | return godot::Memory::alloc_static(p_size); 111 | } 112 | 113 | void *operator new(size_t p_size, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)) { 114 | return p_allocfunc(p_size); 115 | } 116 | 117 | using namespace godot; 118 | 119 | #ifdef _MSC_VER 120 | void operator delete(void *p_mem, const char *p_dummy, const char *p_description) { 121 | ERR_PRINT("Call to placement delete should not happen."); 122 | CRASH_NOW(); 123 | } 124 | 125 | void operator delete(void *p_mem, const char *p_dummy, void *(*p_allocfunc)(size_t p_size)) { 126 | ERR_PRINT("Call to placement delete should not happen."); 127 | CRASH_NOW(); 128 | } 129 | 130 | void operator delete(void *p_mem, const char *p_dummy, void *p_pointer, size_t check, const char *p_description) { 131 | ERR_PRINT("Call to placement delete should not happen."); 132 | CRASH_NOW(); 133 | } 134 | 135 | #endif 136 | -------------------------------------------------------------------------------- /src/variant/vector2i.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* vector2i.cpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #include 34 | 35 | #include 36 | #include 37 | 38 | namespace godot { 39 | 40 | Vector2i Vector2i::clamp(const Vector2i &p_min, const Vector2i &p_max) const { 41 | return Vector2i( 42 | CLAMP(x, p_min.x, p_max.x), 43 | CLAMP(y, p_min.y, p_max.y)); 44 | } 45 | 46 | Vector2i Vector2i::clampi(int32_t p_min, int32_t p_max) const { 47 | return Vector2i( 48 | CLAMP(x, p_min, p_max), 49 | CLAMP(y, p_min, p_max)); 50 | } 51 | 52 | Vector2i Vector2i::snapped(const Vector2i &p_step) const { 53 | return Vector2i( 54 | Math::snapped(x, p_step.x), 55 | Math::snapped(y, p_step.y)); 56 | } 57 | 58 | Vector2i Vector2i::snappedi(int32_t p_step) const { 59 | return Vector2i( 60 | Math::snapped(x, p_step), 61 | Math::snapped(y, p_step)); 62 | } 63 | 64 | int64_t Vector2i::length_squared() const { 65 | return x * (int64_t)x + y * (int64_t)y; 66 | } 67 | 68 | double Vector2i::length() const { 69 | return Math::sqrt((double)length_squared()); 70 | } 71 | 72 | Vector2i Vector2i::operator+(const Vector2i &p_v) const { 73 | return Vector2i(x + p_v.x, y + p_v.y); 74 | } 75 | 76 | void Vector2i::operator+=(const Vector2i &p_v) { 77 | x += p_v.x; 78 | y += p_v.y; 79 | } 80 | 81 | Vector2i Vector2i::operator-(const Vector2i &p_v) const { 82 | return Vector2i(x - p_v.x, y - p_v.y); 83 | } 84 | 85 | void Vector2i::operator-=(const Vector2i &p_v) { 86 | x -= p_v.x; 87 | y -= p_v.y; 88 | } 89 | 90 | Vector2i Vector2i::operator*(const Vector2i &p_v1) const { 91 | return Vector2i(x * p_v1.x, y * p_v1.y); 92 | } 93 | 94 | Vector2i Vector2i::operator*(int32_t p_rvalue) const { 95 | return Vector2i(x * p_rvalue, y * p_rvalue); 96 | } 97 | 98 | void Vector2i::operator*=(int32_t p_rvalue) { 99 | x *= p_rvalue; 100 | y *= p_rvalue; 101 | } 102 | 103 | Vector2i Vector2i::operator/(const Vector2i &p_v1) const { 104 | return Vector2i(x / p_v1.x, y / p_v1.y); 105 | } 106 | 107 | Vector2i Vector2i::operator/(int32_t p_rvalue) const { 108 | return Vector2i(x / p_rvalue, y / p_rvalue); 109 | } 110 | 111 | void Vector2i::operator/=(int32_t p_rvalue) { 112 | x /= p_rvalue; 113 | y /= p_rvalue; 114 | } 115 | 116 | Vector2i Vector2i::operator%(const Vector2i &p_v1) const { 117 | return Vector2i(x % p_v1.x, y % p_v1.y); 118 | } 119 | 120 | Vector2i Vector2i::operator%(int32_t p_rvalue) const { 121 | return Vector2i(x % p_rvalue, y % p_rvalue); 122 | } 123 | 124 | void Vector2i::operator%=(int32_t p_rvalue) { 125 | x %= p_rvalue; 126 | y %= p_rvalue; 127 | } 128 | 129 | Vector2i Vector2i::operator-() const { 130 | return Vector2i(-x, -y); 131 | } 132 | 133 | bool Vector2i::operator==(const Vector2i &p_vec2) const { 134 | return x == p_vec2.x && y == p_vec2.y; 135 | } 136 | 137 | bool Vector2i::operator!=(const Vector2i &p_vec2) const { 138 | return x != p_vec2.x || y != p_vec2.y; 139 | } 140 | 141 | Vector2i::operator String() const { 142 | return "(" + itos(x) + ", " + itos(y) + ")"; 143 | } 144 | 145 | Vector2i::operator Vector2() const { 146 | return Vector2((int32_t)x, (int32_t)y); 147 | } 148 | 149 | } // namespace godot 150 | -------------------------------------------------------------------------------- /src/core/error_macros.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* error_macros.cpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #include 34 | 35 | #include 36 | #include 37 | 38 | #include 39 | 40 | namespace godot { 41 | 42 | void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify, bool p_is_warning) { 43 | if (p_is_warning) { 44 | internal::gdextension_interface_print_warning(p_error, p_function, p_file, p_line, p_editor_notify); 45 | } else { 46 | internal::gdextension_interface_print_error(p_error, p_function, p_file, p_line, p_editor_notify); 47 | } 48 | } 49 | 50 | void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify, bool p_is_warning) { 51 | _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_editor_notify, p_is_warning); 52 | } 53 | 54 | void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify, bool p_is_warning) { 55 | if (p_is_warning) { 56 | internal::gdextension_interface_print_warning_with_message(p_error, p_message, p_function, p_file, p_line, p_editor_notify); 57 | } else { 58 | internal::gdextension_interface_print_error_with_message(p_error, p_message, p_function, p_file, p_line, p_editor_notify); 59 | } 60 | } 61 | 62 | void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify, bool p_is_warning) { 63 | _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message, p_editor_notify, p_is_warning); 64 | } 65 | 66 | void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify, bool p_is_warning) { 67 | _err_print_error(p_function, p_file, p_line, p_error, p_message.utf8().get_data(), p_editor_notify, p_is_warning); 68 | } 69 | 70 | void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify, bool p_is_warning) { 71 | _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message.utf8().get_data(), p_editor_notify, p_is_warning); 72 | } 73 | 74 | void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool p_editor_notify, bool p_fatal) { 75 | String fstr(p_fatal ? "FATAL: " : ""); 76 | String err(fstr + "Index " + p_index_str + " = " + itos(p_index) + " is out of bounds (" + p_size_str + " = " + itos(p_size) + ")."); 77 | _err_print_error(p_function, p_file, p_line, err.utf8().get_data(), p_message, p_editor_notify, false); 78 | } 79 | 80 | void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify, bool p_fatal) { 81 | _err_print_index_error(p_function, p_file, p_line, p_index, p_size, p_index_str, p_size_str, p_message.utf8().get_data(), p_editor_notify, p_fatal); 82 | } 83 | 84 | void _err_flush_stdout() { 85 | fflush(stdout); 86 | } 87 | 88 | } // namespace godot 89 | -------------------------------------------------------------------------------- /include/godot_cpp/core/property_info.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* property_info.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | #include 36 | 37 | #include 38 | 39 | #include 40 | 41 | #include 42 | 43 | #include 44 | 45 | namespace godot { 46 | 47 | struct PropertyInfo { 48 | Variant::Type type = Variant::NIL; 49 | StringName name; 50 | StringName class_name; 51 | uint32_t hint = PROPERTY_HINT_NONE; 52 | String hint_string; 53 | uint32_t usage = PROPERTY_USAGE_DEFAULT; 54 | 55 | PropertyInfo() = default; 56 | 57 | PropertyInfo(Variant::Type p_type, const StringName &p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = "") : 58 | type(p_type), 59 | name(p_name), 60 | hint(p_hint), 61 | hint_string(p_hint_string), 62 | usage(p_usage) { 63 | if (hint == PROPERTY_HINT_RESOURCE_TYPE) { 64 | class_name = hint_string; 65 | } else { 66 | class_name = p_class_name; 67 | } 68 | } 69 | 70 | PropertyInfo(GDExtensionVariantType p_type, const StringName &p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = "") : 71 | PropertyInfo((Variant::Type)p_type, p_name, p_hint, p_hint_string, p_usage, p_class_name) {} 72 | 73 | PropertyInfo(const GDExtensionPropertyInfo *p_info) : 74 | PropertyInfo(p_info->type, *reinterpret_cast(p_info->name), (PropertyHint)p_info->hint, *reinterpret_cast(p_info->hint_string), p_info->usage, *reinterpret_cast(p_info->class_name)) {} 75 | 76 | operator Dictionary() const { 77 | Dictionary dict; 78 | dict["name"] = name; 79 | dict["class_name"] = class_name; 80 | dict["type"] = type; 81 | dict["hint"] = hint; 82 | dict["hint_string"] = hint_string; 83 | dict["usage"] = usage; 84 | return dict; 85 | } 86 | 87 | static PropertyInfo from_dict(const Dictionary &p_dict) { 88 | PropertyInfo pi; 89 | if (p_dict.has("type")) { 90 | pi.type = Variant::Type(int(p_dict["type"])); 91 | } 92 | if (p_dict.has("name")) { 93 | pi.name = p_dict["name"]; 94 | } 95 | if (p_dict.has("class_name")) { 96 | pi.class_name = p_dict["class_name"]; 97 | } 98 | if (p_dict.has("hint")) { 99 | pi.hint = PropertyHint(int(p_dict["hint"])); 100 | } 101 | if (p_dict.has("hint_string")) { 102 | pi.hint_string = p_dict["hint_string"]; 103 | } 104 | if (p_dict.has("usage")) { 105 | pi.usage = p_dict["usage"]; 106 | } 107 | return pi; 108 | } 109 | 110 | void _update(GDExtensionPropertyInfo *p_info) { 111 | p_info->type = (GDExtensionVariantType)type; 112 | *(reinterpret_cast(p_info->name)) = name; 113 | p_info->hint = hint; 114 | *(reinterpret_cast(p_info->hint_string)) = hint_string; 115 | p_info->usage = usage; 116 | *(reinterpret_cast(p_info->class_name)) = class_name; 117 | } 118 | 119 | GDExtensionPropertyInfo _to_gdextension() const { 120 | return { 121 | (GDExtensionVariantType)type, 122 | name._native_ptr(), 123 | class_name._native_ptr(), 124 | hint, 125 | hint_string._native_ptr(), 126 | usage, 127 | }; 128 | } 129 | }; 130 | 131 | } // namespace godot 132 | -------------------------------------------------------------------------------- /include/godot_cpp/variant/char_string.hpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* char_string.hpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #pragma once 34 | 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | namespace godot { 41 | 42 | template 43 | class CharStringT; 44 | 45 | template 46 | class CharProxy { 47 | template 48 | friend class CharStringT; 49 | 50 | const int64_t _index; 51 | CowData &_cowdata; 52 | static inline const T _null = 0; 53 | 54 | _FORCE_INLINE_ CharProxy(const int64_t &p_index, CowData &p_cowdata) : 55 | _index(p_index), 56 | _cowdata(p_cowdata) {} 57 | 58 | public: 59 | _FORCE_INLINE_ CharProxy(const CharProxy &p_other) : 60 | _index(p_other._index), 61 | _cowdata(p_other._cowdata) {} 62 | 63 | _FORCE_INLINE_ operator T() const { 64 | if (unlikely(_index == _cowdata.size())) { 65 | return _null; 66 | } 67 | 68 | return _cowdata.get(_index); 69 | } 70 | 71 | _FORCE_INLINE_ const T *operator&() const { 72 | return _cowdata.ptr() + _index; 73 | } 74 | 75 | _FORCE_INLINE_ void operator=(const T &p_other) const { 76 | _cowdata.set(_index, p_other); 77 | } 78 | 79 | _FORCE_INLINE_ void operator=(const CharProxy &p_other) const { 80 | _cowdata.set(_index, p_other.operator T()); 81 | } 82 | }; 83 | 84 | template 85 | class CharStringT { 86 | friend class String; 87 | 88 | CowData _cowdata; 89 | static inline const T _null = 0; 90 | 91 | public: 92 | _FORCE_INLINE_ T *ptrw() { return _cowdata.ptrw(); } 93 | _FORCE_INLINE_ const T *ptr() const { return _cowdata.ptr(); } 94 | _FORCE_INLINE_ int64_t size() const { return _cowdata.size(); } 95 | Error resize(int64_t p_size) { return _cowdata.resize(p_size); } 96 | 97 | _FORCE_INLINE_ T get(int64_t p_index) const { return _cowdata.get(p_index); } 98 | _FORCE_INLINE_ void set(int64_t p_index, const T &p_elem) { _cowdata.set(p_index, p_elem); } 99 | _FORCE_INLINE_ const T &operator[](int64_t p_index) const { 100 | if (unlikely(p_index == _cowdata.size())) { 101 | return _null; 102 | } 103 | 104 | return _cowdata.get(p_index); 105 | } 106 | _FORCE_INLINE_ CharProxy operator[](int64_t p_index) { return CharProxy(p_index, _cowdata); } 107 | 108 | _FORCE_INLINE_ CharStringT() {} 109 | _FORCE_INLINE_ CharStringT(const CharStringT &p_str) { _cowdata._ref(p_str._cowdata); } 110 | _FORCE_INLINE_ void operator=(const CharStringT &p_str) { _cowdata._ref(p_str._cowdata); } 111 | _FORCE_INLINE_ CharStringT(const T *p_cstr) { copy_from(p_cstr); } 112 | 113 | void operator=(const T *p_cstr); 114 | bool operator<(const CharStringT &p_right) const; 115 | CharStringT &operator+=(T p_char); 116 | int64_t length() const { return size() ? size() - 1 : 0; } 117 | const T *get_data() const; 118 | operator const T *() const { return get_data(); }; 119 | 120 | protected: 121 | void copy_from(const T *p_cstr); 122 | }; 123 | 124 | template <> 125 | const char *CharStringT::get_data() const; 126 | 127 | template <> 128 | const char16_t *CharStringT::get_data() const; 129 | 130 | template <> 131 | const char32_t *CharStringT::get_data() const; 132 | 133 | template <> 134 | const wchar_t *CharStringT::get_data() const; 135 | 136 | typedef CharStringT CharString; 137 | typedef CharStringT Char16String; 138 | typedef CharStringT Char32String; 139 | typedef CharStringT CharWideString; 140 | 141 | } // namespace godot 142 | -------------------------------------------------------------------------------- /src/core/object.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* object.cpp */ 3 | /**************************************************************************/ 4 | /* This file is part of: */ 5 | /* REDOT ENGINE */ 6 | /* https://redotengine.org */ 7 | /**************************************************************************/ 8 | /* Copyright (c) 2024-present Redot Engine contributors */ 9 | /* (see REDOT_AUTHORS.md) */ 10 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ 11 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ 12 | /* */ 13 | /* Permission is hereby granted, free of charge, to any person obtaining */ 14 | /* a copy of this software and associated documentation files (the */ 15 | /* "Software"), to deal in the Software without restriction, including */ 16 | /* without limitation the rights to use, copy, modify, merge, publish, */ 17 | /* distribute, sublicense, and/or sell copies of the Software, and to */ 18 | /* permit persons to whom the Software is furnished to do so, subject to */ 19 | /* the following conditions: */ 20 | /* */ 21 | /* The above copyright notice and this permission notice shall be */ 22 | /* included in all copies or substantial portions of the Software. */ 23 | /* */ 24 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ 25 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ 26 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ 27 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ 28 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ 29 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ 30 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ 31 | /**************************************************************************/ 32 | 33 | #include 34 | 35 | #include 36 | 37 | namespace godot { 38 | 39 | namespace internal { 40 | 41 | Object *get_object_instance_binding(GodotObject *p_engine_object) { 42 | if (p_engine_object == nullptr) { 43 | return nullptr; 44 | } 45 | 46 | // Get existing instance binding, if one already exists. 47 | GDExtensionObjectPtr instance = gdextension_interface_object_get_instance_binding(p_engine_object, token, nullptr); 48 | if (instance != nullptr) { 49 | return reinterpret_cast(instance); 50 | } 51 | 52 | // Otherwise, try to look up the correct binding callbacks. 53 | const GDExtensionInstanceBindingCallbacks *binding_callbacks = nullptr; 54 | StringName class_name; 55 | if (gdextension_interface_object_get_class_name(p_engine_object, library, reinterpret_cast(class_name._native_ptr()))) { 56 | binding_callbacks = ClassDB::get_instance_binding_callbacks(class_name); 57 | } 58 | if (binding_callbacks == nullptr) { 59 | binding_callbacks = &Object::_gde_binding_callbacks; 60 | } 61 | 62 | return reinterpret_cast(gdextension_interface_object_get_instance_binding(p_engine_object, token, binding_callbacks)); 63 | } 64 | 65 | TypedArray convert_property_list(const std::vector &p_list) { 66 | TypedArray va; 67 | for (const PropertyInfo &pi : p_list) { 68 | va.push_back(Dictionary(pi)); 69 | } 70 | return va; 71 | } 72 | 73 | } // namespace internal 74 | 75 | MethodInfo::operator Dictionary() const { 76 | Dictionary dict; 77 | dict["name"] = name; 78 | dict["args"] = internal::convert_property_list(arguments); 79 | Array da; 80 | for (size_t i = 0; i < default_arguments.size(); i++) { 81 | da.push_back(default_arguments[i]); 82 | } 83 | dict["default_args"] = da; 84 | dict["flags"] = flags; 85 | dict["id"] = id; 86 | Dictionary r = return_val; 87 | dict["return"] = r; 88 | return dict; 89 | } 90 | 91 | MethodInfo MethodInfo::from_dict(const Dictionary &p_dict) { 92 | MethodInfo mi; 93 | 94 | if (p_dict.has("name")) { 95 | mi.name = p_dict["name"]; 96 | } 97 | Array args; 98 | if (p_dict.has("args")) { 99 | args = p_dict["args"]; 100 | } 101 | 102 | for (int i = 0; i < args.size(); i++) { 103 | Dictionary d = args[i]; 104 | mi.arguments.push_back(PropertyInfo::from_dict(d)); 105 | } 106 | Array defargs; 107 | if (p_dict.has("default_args")) { 108 | defargs = p_dict["default_args"]; 109 | } 110 | for (int i = 0; i < defargs.size(); i++) { 111 | mi.default_arguments.push_back(defargs[i]); 112 | } 113 | 114 | if (p_dict.has("return")) { 115 | mi.return_val = PropertyInfo::from_dict(p_dict["return"]); 116 | } 117 | 118 | if (p_dict.has("flags")) { 119 | mi.flags = p_dict["flags"]; 120 | } 121 | 122 | return mi; 123 | } 124 | 125 | MethodInfo::MethodInfo() : 126 | flags(GDEXTENSION_METHOD_FLAG_NORMAL) {} 127 | 128 | MethodInfo::MethodInfo(StringName p_name) : 129 | name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {} 130 | 131 | MethodInfo::MethodInfo(Variant::Type ret) : 132 | flags(GDEXTENSION_METHOD_FLAG_NORMAL) { 133 | return_val.type = ret; 134 | } 135 | 136 | MethodInfo::MethodInfo(Variant::Type ret, StringName p_name) : 137 | name(p_name), flags(GDEXTENSION_METHOD_FLAG_NORMAL) { 138 | return_val.type = ret; 139 | } 140 | 141 | MethodInfo::MethodInfo(const PropertyInfo &p_ret, StringName p_name) : 142 | name(p_name), return_val(p_ret), flags(GDEXTENSION_METHOD_FLAG_NORMAL) {} 143 | 144 | } // namespace godot 145 | --------------------------------------------------------------------------------