Compare commits

..

61 Commits

Author SHA1 Message Date
David Snopek
d5cc777a89 Merge pull request #1803 from dsnopek/4.3-cherrypicks-5
Cherry-picks for the godot-cpp 4.3 branch - 5th batch
2025-07-03 08:52:49 -05:00
David Snopek
b1e2ac5cbb Update CI to use windows-2022
(cherry picked from commit 8938e7e4e3)
2025-06-25 09:16:25 -05:00
David Snopek
53caa6adbc Update CI to use ubuntu-22.04 2025-06-24 14:50:16 -05:00
Tom
a9abdb5f0c Cleaned up the MethodBind class
(cherry picked from commit ca5af3c861)
2025-06-24 12:49:39 -05:00
MJacred
9892f63abb Fix URL to gdextension cpp example in the official docs
(cherry picked from commit f25c4df5c4)
2025-06-24 12:49:28 -05:00
Lukas Tenbrink
7b4ca64761 Make ndk version configurable as a command-like argument.
(cherry picked from commit 16e47d7ae5)
2025-06-24 12:49:17 -05:00
Fabio Alessandrelli
6cdac999c2 fix: Add iOS min SDK version link flags
This is required when publishing to the App Store, and consistent with
what we already do for the macOS deployment target.

(cherry picked from commit 4879eb7bd0)
2025-06-24 12:45:39 -05:00
David Snopek
48544896ee Stop referring to GDExtension as experimental in the README
(cherry picked from commit 7660dd28b3)
2025-06-24 12:45:29 -05:00
Ben Lubar
443c075fa3 fix iterators making unintended copies
(cherry picked from commit 7fd0999b3c)
2025-06-24 12:45:14 -05:00
David Snopek
52937a3850 Fix classes without _to_string() always returning "[Wrapped:0]"
(cherry picked from commit f38c056b67)
2025-06-24 12:43:31 -05:00
Thaddeus Crews
888f46bbcc SCons: Add CPPEXTPATH for external includes
(cherry picked from commit 30bfa6f215)
2025-06-24 12:43:21 -05:00
Aaron Franke
de7e5b9145 Add missing Projection constructor with 16 real_t values
(cherry picked from commit aa03c32b3e)
2025-06-24 12:42:28 -05:00
David Snopek
8fffe3b558 Fix stack smashing when Godot methods return char32_t, char16_t or wchar_t
(cherry picked from commit 035add9d4f)
2025-06-24 12:42:10 -05:00
David Snopek
dcd0842fab Merge pull request #1744 from dsnopek/4.3-cherrypicks-4
Cherry-picks for the godot-cpp 4.3 branch - 4th batch
2025-03-18 08:08:42 -05:00
zhmt
dacaa81f2f binding_generator.py: Don't error if directory already exists
It should be ok when folders exist. Exception shouldn't be thrown.

Update binding_generator.py

It should be ok when folds exist. It will fail to build without this patch,  in vs code on windows with compiler ( visual studio community 2022 amd 64) .

Co-Authored-By: Chris Cranford <ccranfor@redhat.com>
(cherry picked from commit d79959c79e)
2025-03-17 10:52:48 -05:00
David Snopek
40e65753f9 Check that precision of extension_api.json matches build options
(cherry picked from commit 0a73df5f53)
2025-03-17 10:52:37 -05:00
Thaddeus Crews
2dee0cc4de Style: Replace _NO_DISCARD_ macro with [[nodiscard]]
(cherry picked from commit 89fd27608f)
2025-03-17 10:50:49 -05:00
dependabot[bot]
3f454d142d Bump actions/upload-artifact from 3 to 4
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit b17e668c15)
2025-03-17 10:48:14 -05:00
David Snopek
f3a1a2fd45 Merge pull request #1695 from dsnopek/4.3-cherrypicks-3
Cherry-picks for the godot-cpp 4.3 branch - 3rd batch
2025-01-28 11:28:57 -06:00
Brecht Kuppens
08e4c89da9 Fix buffer overrun with enums pointers cast to int64_t* when enum is only 32-bit
(cherry picked from commit 7576dc5930)
2025-01-28 10:37:36 -06:00
Brecht Kuppens
86d0dbe695 Update README.md with new pre-commit instructions
(cherry picked from commit bd3cf478c6)
2025-01-28 10:37:36 -06:00
Fabio Alessandrelli
dc87cb6b97 [CI] Re-add generated files consistency check
(cherry picked from commit 0cfe01eff2)
2025-01-28 10:37:36 -06:00
Fabio Alessandrelli
4b9cd6ae9d [Bindings] Build profile now strips methods and skip files
This allows removing dependencies that are not explicitly unused by the
gdextension being built and is implemented using an intermediate json
API file with the methods and classes stripped (i.e. without touching
the file generators).

(cherry picked from commit c4f1abe3f9)
2025-01-28 10:37:36 -06:00
David Snopek
fba9ecd0da Fix print_verbose() macro conflicting with UtilityFunctions::print_verbose()
(cherry picked from commit 47d9cb9bed)
2025-01-28 10:37:36 -06:00
Lukas Tenbrink
59ad323dd1 Add a separate setup-godot-cpp github action.
(cherry picked from commit 9943675dcb)
2025-01-28 10:37:36 -06:00
Aaron Franke
9dc2e15d90 Add print_line for compatibility with engine modules
(cherry picked from commit ac466e4766)
2025-01-28 10:37:36 -06:00
A Thousand Ships
2d96b62774 [Web] Don't cache emsdk
Due to how caches are accessed this cache is almost useless, it only
matters if it is from the same branch or a base branch, and is identical
between branches, so caching it just clutters the build cache

(cherry picked from commit 1e3b24f658)
2025-01-28 10:37:36 -06:00
David Snopek
2cd6221286 Sync Quaternion with the version in Godot
(cherry picked from commit 2004af63a0)
2025-01-28 10:37:36 -06:00
ruffenman
d6a47a28c7 Remove unimplemented static variant functions 'blend' and 'interpolate'. If a user attempts to call either of these it will introduce a linker error and it may not be immediately clear to them why. Also, variant interpolation can already be accessed via 'UtilityFunctions::lerp', making at least the interpolate function unecessary here.
(cherry picked from commit 42a35a1852)
2025-01-28 10:37:36 -06:00
Thaddeus Crews
f2303ba0cc CI: Add runner workflow to call other workflows
(cherry picked from commit c1524f7c86)
2025-01-28 10:37:36 -06:00
Zhehang Ding
c9da56cca2 Use namespace in defs.hpp
A global alias of godot::real_t is defined for backward compatibility

(cherry picked from commit 450c3d65cd)
2025-01-28 10:37:36 -06:00
David Snopek
3449c4e1d3 Don't print an error when decoding a null Ref<T>
(cherry picked from commit 7f02301a91)
2025-01-28 10:37:36 -06:00
Lukas Tenbrink
0899cf6098 Rename Vector4.components -> coords.
The use of .components is deprecated.

(cherry picked from commit 23c9d41d2a)
2025-01-28 10:37:36 -06:00
Lukas Tenbrink
06fbf3ce95 Add lto scons option, defaulting to "none".
(cherry picked from commit 5f7cf05043)
2025-01-28 10:37:36 -06:00
David Snopek
d5bdde9509 Avoid thread_local on MacOS to prevent issues with hot reload
(cherry picked from commit 91833c852e)
2025-01-28 10:37:36 -06:00
David Snopek
9ded2402dc Fix crash in ClassDB::add_virtual_method() if arguments metadata is the wrong size
(cherry picked from commit 1e169bb809)
2025-01-28 10:37:36 -06:00
David Snopek
575f317bf1 [4.3] Run tests against Godot 4.3-stable 2025-01-28 10:37:36 -06:00
David Snopek
56571dc584 Merge pull request #1632 from dsnopek/4.3-cherrypicks-2
Cherry-picks for the godot-cpp 4.3 branch - 2nd batch
2024-10-30 09:38:31 -05:00
Florent Guiocheau
94d74979ce Add p_use_model_front to Basis::looking_at()
(cherry picked from commit 02fd535454)
2024-10-28 16:32:13 -05:00
Thaddeus Crews
bf26191ead SCons: Don't cache librarys
(cherry picked from commit 83c0f15ab9)
2024-10-28 16:32:02 -05:00
Fabio Alessandrelli
af78f2778f [SCons] Enable WASM_BIGINT in web builds
Required since Godot 4.3, which is also the first Godot version with
wide WASM gdnative support (previous versions were Chrome-only, and very
brittle).

(cherry picked from commit 78498da7c3)
2024-10-28 16:31:51 -05:00
Fabio Alessandrelli
30a395bf43 [SCons] Remove use_clang_cl windows flag in favor of generic use_llvm
This is consistent with Godot upstream.

(cherry picked from commit 4717a78144)
2024-10-28 16:31:40 -05:00
Samuel Nicholas
a3d5d6d4d3 VSProj Configure type on build command - to resolve #1582
Visual Studio projects are multi-config projects like Ninja-MultiConfig which means you can't set the configuration at configure time as there are multiple, it always chooses the first one by default when not specified in the build command.

Instead of this:
cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 17 2022" .
cmake --build . --verbose

It should be this
cmake -G"Visual Studio 17 2022" .
cmake --build . --verbose --config Release

Update ci.yml

Because the current build system doesnt use generator expressions for multi config builds, both the CMAKE_BUILD_TYPE and the build --config options need to be set

(cherry picked from commit 07704f8f48)
2024-10-28 16:31:31 -05:00
Samuel Nicholas
e751531290 update .gitignore to add .idea for the Jetbrains CLion IDE
and also the default cmake build directory when building in clion cmake-build-*

(cherry picked from commit 9f5daa2d90)
2024-10-28 16:31:22 -05:00
Samuel Nicholas
2de650b82a Re-Structure cmake solution to be closer to the scons solution.
This is just a single step, re-arranging the code without actually changing its functionality.

new docs/cmake.md
moved the block of comments from the start of the CMakeLists.txt into the cmake.md file and converted content to markdown.

new cmake/godotcpp.cmake
Moved all exposed options into a new function godotcpp_options()
Moved configuration and generation code into godotcpp_generate()

To get all the options into the godotcpp_options() I changed the logic of GODOT_USE_HOT_RELOAD which I believe is a closer match to scons, that if the options is not set, and the build type is not release, then it defaults to ON.

I msvc builds require the default flags to be modified or it will throw errors. I have added the links to articles in the commit, but its about removing the runtime error checks /RTC1 from the CMAKE_CXX_FLAGS_DEBUG variable. This needs to happen before the files are included.
https://stackoverflow.com/questions/74426638/how-to-remove-rtc1-from-specific-target-or-file-in-cmake
https://discourse.cmake.org/t/how-do-i-remove-compile-options-from-target/5965

Renamed GodotCompilerWarnings.cmake to common_compiler_flags.cmake to match scons

Included files explicitly by path, as we dont need to append to the CMAKE_MODULES_PATH which effects the whole build tree.

This prevents consumers of the library from clobbering the names of the cmake include files and breaking the build.

(cherry picked from commit 2402a044eb)
2024-10-28 16:31:12 -05:00
David Snopek
5fe58bcd1e Correctly set instance bindings on reload
(cherry picked from commit cb543c192a)
2024-10-28 16:31:03 -05:00
Samuel Nicholas
daf8ac1c33 Updated all variable names to use GODOT_ prefix
changed cache type for api file and api dir to FILEPATH and PATH respectively.
Minor whitespace.
docstring parity

(cherry picked from commit 390a9a5590)
2024-10-28 16:30:54 -05:00
Samuel Nicholas
b12aeb1b38 Add GODOT_SYMBOL_VISIBILITY cache variable to match scons interface.
(cherry picked from commit 02bdc6665a)
2024-10-28 16:30:45 -05:00
Andreas Pokorny
fa0b4cffc0 Add visibility-hidden
This should make all symbols that are not marked otherwise have hidden
visibility. There still may be exposed symbols if marked with respective
attributes.

(cherry picked from commit d18fa929fb)
2024-10-28 16:30:35 -05:00
ytnuf
e52b4ea4fd Add hot reload support when building with GCC and CMake
(cherry picked from commit 05571971cc)
2024-10-28 16:30:21 -05:00
bruvzg
20459da676 Add support for LLVM/MinGW and ARM64 Windows builds.
(cherry picked from commit f2353da5a3)
2024-10-28 16:30:12 -05:00
David Snopek
1cce4d15ab Merge pull request #1592 from dsnopek/4.3-revert-unexpose-is-instance-valid
[4.3] Revert "Unexpose `UtilityFunctions::is_instance_valid()`"
2024-09-23 10:46:45 -05:00
David Snopek
17ca325aeb Revert "Unexpose UtilityFunctions::is_instance_valid()"
This reverts commit 56cd3fd99e.
2024-09-17 10:03:25 -05:00
David Snopek
e298f430b5 Merge pull request #1569 from dsnopek/4.3-cherrypicks-1
Cherry-picks for the godot-cpp 4.3 branch - 1st batch
2024-09-11 17:17:24 -05:00
David Snopek
1ac33c906e Add a test to ensure that library path is absolute
(cherry picked from commit 92ace04989)
2024-09-03 16:35:55 -05:00
George L. Albany
842a7f621f Fix GCC 14 -Wtemplate-id-cdtor warning
As was fixed with godotengine/godot#91208

(cherry picked from commit 7b31f39bea)
2024-09-03 16:35:31 -05:00
Fabio Alessandrelli
37d255af6c [Web/SCons] Use CCFLAGS for SIDE_MODULE option
Was using CPPFLAGS, but should use the explicit scons CCFLAGS which
makes it clear they are applied to both the C and C++ compiler.

CPPFLAGS was also fine (they are preprocessor flags, also applied to
both C and C++), but we should try to stay consistent with what we do
in Godot.

(cherry picked from commit f36acd8e31)
2024-09-03 16:35:21 -05:00
Aaron Franke
762db4e4d6 Fix missing MAKE_TYPED_ARRAY_INFO for Packed*Arrays
(cherry picked from commit 10c3d1bc5f)
2024-09-03 16:35:11 -05:00
Raul Santos
c823e84ff2 Correct type for char16 and char32 meta 2024-09-03 16:35:02 -05:00
Mikael Hermansson
26cb3292a0 Fix incorrect generation of some C++ operators 2024-09-03 16:34:54 -05:00
Raul Santos
150e45071b Avoid hardcoded type conversion for metadata
The engine uses the names `int` and `float` to refer to the 64-bit types, so in the bindings generator we have a hardcoded conversion for those types.

But this type conversion should not be used for metadata. Even though the underlying type should still be 64-bit for interop, metadata is meant to specify the correct type to expose. So if metadata says `float` it means the type is really meant to be a 32-bit `float` and not `double`. Other hardcoded type conversions (`int` and `Nil`) won't ever be metadata.

This change corrects the `float` type, to use the right type in the generated C++ code. Before we were always using `double` due to this type conversion.

(cherry picked from commit 4829199081)
2024-09-03 16:34:41 -05:00
139 changed files with 4189 additions and 45641 deletions

View File

@@ -1,105 +1,80 @@
# Commented out parameters are those with the same value as base LLVM style.
# We can uncomment them if we want to change their value, or enforce the
# chosen value in case the base style changes (last sync: Clang 17.0.6).
BasedOnStyle: LLVM
# chosen value in case the base style changes (last sync: Clang 14.0).
---
### General config, applies to all languages ###
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign
# AlignArrayOfStructures: None
# AlignConsecutiveAssignments:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCompound: false
# PadOperators: true
# AlignConsecutiveBitFields:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCompound: false
# PadOperators: false
# AlignConsecutiveDeclarations:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCompound: false
# PadOperators: false
# AlignConsecutiveMacros:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCompound: false
# PadOperators: false
# AlignConsecutiveShortCaseStatements:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCaseColons: false
# AlignConsecutiveMacros: None
# AlignConsecutiveAssignments: None
# AlignConsecutiveBitFields: None
# AlignConsecutiveDeclarations: None
# AlignEscapedNewlines: Right
AlignOperands: DontAlign
AlignTrailingComments:
Kind: Never
OverEmptyLines: 0
AlignOperands: DontAlign
AlignTrailingComments: false
# AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
# AllowShortEnumsOnASingleLine: true
# AllowShortBlocksOnASingleLine: Never
# AllowShortCaseLabelsOnASingleLine: false
# AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
# AllowShortIfStatementsOnASingleLine: Never
# AllowShortFunctionsOnASingleLine: All
# AllowShortLambdasOnASingleLine: All
# AllowShortIfStatementsOnASingleLine: Never
# AllowShortLoopsOnASingleLine: false
# AlwaysBreakAfterDefinitionReturnType: None
# AlwaysBreakAfterReturnType: None
# AlwaysBreakBeforeMultilineStrings: false
# AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- _ALWAYS_INLINE_
- _FORCE_INLINE_
- _NO_INLINE_
# AttributeMacros:
# - __capability
# BinPackArguments: true
# BinPackParameters: true
# BitFieldColonSpacing: Both
# BraceWrapping:
# AfterCaseLabel: false
# AfterClass: false
# AfterCaseLabel: false
# AfterClass: false
# AfterControlStatement: Never
# AfterEnum: false
# AfterFunction: false
# AfterNamespace: false
# AfterEnum: false
# AfterFunction: false
# AfterNamespace: false
# AfterObjCDeclaration: false
# AfterStruct: false
# AfterUnion: false
# AfterStruct: false
# AfterUnion: false
# AfterExternBlock: false
# BeforeCatch: false
# BeforeElse: false
# BeforeCatch: false
# BeforeElse: false
# BeforeLambdaBody: false
# BeforeWhile: false
# IndentBraces: false
# BeforeWhile: false
# IndentBraces: false
# SplitEmptyFunction: true
# SplitEmptyRecord: true
# SplitEmptyNamespace: true
# BreakAfterAttributes: Never
# BreakAfterJavaFieldAnnotations: false
# BreakArrays: true
# BreakBeforeBinaryOperators: None
# BreakBeforeConceptDeclarations: true
# BreakBeforeBraces: Attach
# BreakBeforeConceptDeclarations: Always
# BreakBeforeInlineASMColon: OnlyMultiline
# BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon
# BreakBeforeInheritanceComma: false
# BreakInheritanceList: BeforeColon
# BreakBeforeTernaryOperators: true
# BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: AfterColon
# BreakStringLiterals: true
ColumnLimit: 0
# CommentPragmas: "^ IWYU pragma:"
ColumnLimit: 0
# CommentPragmas: '^ IWYU pragma:'
# QualifierAlignment: Leave
# CompactNamespaces: false
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: false
# DeriveLineEnding: true
# DerivePointerAlignment: false
# DisableFormat: false
# DisableFormat: false
# EmptyLineAfterAccessModifier: Never
# EmptyLineBeforeAccessModifier: LogicalBlock
# ExperimentalAutoDetectBinPacking: false
# PackConstructorInitializers: BinPack
ConstructorInitializerAllOnOneLineOrOnePerLine: true
# AllowAllConstructorInitializersOnNextLine: true
# FixNamespaceComments: true
# ForEachMacros:
# - foreach
@@ -107,61 +82,34 @@ Cpp11BracedListStyle: false
# - BOOST_FOREACH
# IfMacros:
# - KJ_IF_MAYBE
# IncludeBlocks: Preserve
# IncludeBlocks: Preserve
IncludeCategories:
- Regex: ^".*"$
Priority: 1
- Regex: ^<.*\.h>$
Priority: 2
- Regex: ^<.*>$
Priority: 3
# IncludeIsMainRegex: (Test)?$
# IncludeIsMainSourceRegex: ""
- Regex: '".*"'
Priority: 1
- Regex: '^<.*\.h>'
Priority: 2
- Regex: '^<.*'
Priority: 3
# IncludeIsMainRegex: '(Test)?$'
# IncludeIsMainSourceRegex: ''
# IndentAccessModifiers: false
# IndentCaseBlocks: false
IndentCaseLabels: true
# IndentExternBlock: AfterExternBlock
# IndentCaseBlocks: false
# IndentGotoLabels: true
# IndentPPDirectives: None
# IndentRequiresClause: true
IndentWidth: 4
# IndentExternBlock: AfterExternBlock
# IndentRequires: false
IndentWidth: 4
# IndentWrappedFunctionNames: false
InsertBraces: true
# InsertNewlineAtEOF: false
# InsertTrailingCommas: None
# IntegerLiteralSeparator:
# Binary: 0
# BinaryMinDigits: 0
# Decimal: 0
# DecimalMinDigits: 0
# Hex: 0
# HexMinDigits: 0
JavaImportGroups:
- org.godotengine
- android
- androidx
- com.android
- com.google
- java
- javax
# JavaScriptQuotes: Leave
# JavaScriptWrapImports: true
# KeepEmptyLinesAtEOF: false
KeepEmptyLinesAtTheStartOfBlocks: false
# LambdaBodyIndentation: Signature
# Language: Cpp
# LineEnding: DeriveLF
# MacroBlockBegin: ""
# MacroBlockEnd: ""
# MacroBlockBegin: ''
# MacroBlockEnd: ''
# MaxEmptyLinesToKeep: 1
# NamespaceIndentation: None
# ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
# ObjCBreakBeforeNestedBlockParam: true
# ObjCSpaceAfterProperty: false
# ObjCSpaceBeforeProtocolList: true
# PPIndentWidth: -1
PackConstructorInitializers: NextLine
# PenaltyBreakAssignment: 2
# PenaltyBreakBeforeFirstCallParameter: 19
# PenaltyBreakComment: 300
@@ -170,71 +118,82 @@ PackConstructorInitializers: NextLine
# PenaltyBreakString: 1000
# PenaltyBreakTemplateDeclaration: 10
# PenaltyExcessCharacter: 1000000
# PenaltyIndentedWhitespace: 0
# PenaltyReturnTypeOnItsOwnLine: 60
# PenaltyIndentedWhitespace: 0
# PointerAlignment: Right
# QualifierAlignment: Leave
# PPIndentWidth: -1
# ReferenceAlignment: Pointer
# ReflowComments: true
# ReflowComments: true
# RemoveBracesLLVM: false
# RemoveParentheses: Leave
RemoveSemicolon: true
# RequiresClausePosition: OwnLine
# RequiresExpressionIndentation: OuterScope
# SeparateDefinitionBlocks: Leave
# ShortNamespaceLines: 1
# SortIncludes: CaseSensitive
# SortIncludes: CaseSensitive
# SortJavaStaticImport: Before
# SortUsingDeclarations: LexicographicNumeric
# SortUsingDeclarations: true
# SpaceAfterCStyleCast: false
# SpaceAfterLogicalNot: false
# SpaceAfterTemplateKeyword: true
# SpaceAroundPointerQualifiers: Default
# SpaceBeforeAssignmentOperators: true
# SpaceBeforeCaseColon: false
# SpaceBeforeCpp11BracedList: false
# SpaceBeforeCtorInitializerColon: true
# SpaceBeforeInheritanceColon: true
# SpaceBeforeJsonColon: false
# SpaceBeforeParens: ControlStatements
# SpaceBeforeParensOptions:
# AfterControlStatements: true
# AfterForeachMacros: true
# AfterFunctionDeclarationName: false
# AfterFunctionDefinitionName: false
# AfterIfMacros: true
# AfterFunctionDeclarationName: false
# AfterIfMacros: true
# AfterOverloadedOperator: false
# AfterRequiresInClause: false
# AfterRequiresInExpression: false
# BeforeNonEmptyParentheses: false
# SpaceAroundPointerQualifiers: Default
# SpaceBeforeRangeBasedForLoopColon: true
# SpaceBeforeSquareBrackets: false
# SpaceInEmptyBlock: false
# SpaceInEmptyParentheses: false
# SpacesBeforeTrailingComments: 1
# SpacesInAngles: Never
# SpacesInAngles: Never
# SpacesInConditionalStatement: false
# SpacesInContainerLiterals: true
# SpacesInCStyleCastParentheses: false
## Godot TODO: We'll want to use a min of 1, but we need to see how to fix
## our comment capitalization at the same time.
SpacesInLineCommentPrefix:
Minimum: 0 # We want a minimum of 1 for comments, but allow 0 for disabled code.
Maximum: -1
# SpacesInParens: Never
# SpacesInParensOptions:
# InConditionalStatements: false
# InCStyleCasts: false
# InEmptyParentheses: false
# Other: false
Minimum: 0
Maximum: -1
# SpacesInParentheses: false
# SpacesInSquareBrackets: false
Standard: c++20
# SpaceBeforeSquareBrackets: false
# BitFieldColonSpacing: Both
# StatementAttributeLikeMacros:
# - Q_EMIT
# StatementMacros:
# - Q_UNUSED
# - QT_REQUIRE_VERSION
TabWidth: 4
UseTab: Always
# VerilogBreakBetweenInstancePorts: true
TabWidth: 4
# UseCRLF: false
UseTab: Always
# WhitespaceSensitiveMacros:
# - BOOST_PP_STRINGIZE
# - CF_SWIFT_NAME
# - NS_SWIFT_NAME
# - PP_STRINGIZE
# - STRINGIZE
# - PP_STRINGIZE
# - BOOST_PP_STRINGIZE
# - NS_SWIFT_NAME
# - CF_SWIFT_NAME
---
### C++ specific config ###
Language: Cpp
Standard: c++17
---
### ObjC specific config ###
Language: ObjC
# ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
# ObjCBreakBeforeNestedBlockParam: true
# ObjCSpaceAfterProperty: false
# ObjCSpaceBeforeProtocolList: true
---
### Java specific config ###
Language: Java
# BreakAfterJavaFieldAnnotations: false
JavaImportGroups: ['org.godotengine', 'android', 'androidx', 'com.android', 'com.google', 'java', 'javax']
...

View File

@@ -6,12 +6,11 @@ end_of_line = lf
indent_size = 4
indent_style = tab
insert_final_newline = true
max_line_length = 120
trim_trailing_whitespace = true
[{*.py,SConstruct}]
indent_style = space
[{*.{yml,yaml},.clang-format}]
[*.{yml,yaml}]
indent_size = 2
indent_style = space

View File

@@ -1,11 +0,0 @@
# This file contains a list of Git commit hashes that should be hidden from the
# regular Git history. Typically, this includes commits involving mass auto-formatting
# or other normalizations. Commit hashes *must* use the full 40-character notation.
# To apply the ignore list in your local Git client, you must run:
#
# git config blame.ignoreRevsFile .git-blame-ignore-revs
#
# This file is automatically used by GitHub.com's blame view.
# Style: Replace header guards with `#pragma once`
7056c996dd43ae1aa466c94d95cc2fe63853d8a9

View File

@@ -20,16 +20,12 @@ inputs:
default: 12.2.0
description: MinGW version.
ndk-version:
default: r28b
default: r23c
description: Android NDK version.
buildtool:
default: scons
description: scons or cmake
scons-version:
default: 4.4.0
description: SCons version.
runs:
using: composite
steps:
@@ -59,13 +55,8 @@ runs:
version: ${{ inputs.mingw-version }}
- name: Setup SCons
if: ${{ inputs.buildtool == 'scons' }}
shell: bash
run: |
python -c "import sys; print(sys.version)"
python -m pip install scons==${{ inputs.scons-version }}
scons --version
- name: Install Ninja
if: ${{ inputs.buildtool == 'cmake' }}
uses: ashutoshvarma/setup-ninja@master

View File

@@ -1,186 +0,0 @@
name: Continuous integration
on:
workflow_call:
env:
# Only used for the cache key. Increment version to force clean build.
GODOT_BASE_BRANCH: master
# Used to select the version of Godot to run the tests with.
GODOT_TEST_VERSION: master
# Use UTF-8 on Linux.
LANG: en_US.UTF-8
LC_ALL: en_US.UTF-8
concurrency:
group: ci-cmake-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-cmake:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
env:
EM_VERSION: 3.1.39
config-flags:
-DCMAKE_C_COMPILER_LAUNCHER=sccache
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache
-DGODOTCPP_ENABLE_TESTING=ON
-DGODOTCPP_BUILD_PROFILE="test/build_profile.json"
SCCACHE_GHA_ENABLED: "true"
strategy:
fail-fast: false
matrix:
include:
- name: 🐧 Linux (GCC, Makefiles)
os: ubuntu-22.04
platform: linux
config-flags: -DCMAKE_BUILD_TYPE=Release
artifact-name: godot-cpp-linux-glibc2.27-x86_64-release.cmake
artifact-path: cmake-build/bin/libgodot-cpp.linux.template_release.x86_64.a
run-tests: true
- name: 🏁 Windows (x86_64, MSVC)
os: windows-2022
platform: windows
compiler: msvc
build-flags: --config Release
artifact-name: godot-cpp-windows-msvc2019-x86_64-release.cmake
artifact-path: cmake-build/bin/libgodot-cpp.windows.template_release.x86_64.lib
run-tests: false
- name: 🏁 Windows (x86_64, MinGW, Ninja)
os: windows-2022
platform: windows
compiler: mingw
config-flags:
-GNinja -DCMAKE_BUILD_TYPE=Release
-DCMAKE_CXX_COMPILER=cc -DCMAKE_CXX_COMPILER=c++
artifact-name: godot-cpp-linux-mingw-x86_64-release.cmake
artifact-path: cmake-build/bin/libgodot-cpp.windows.template_release.x86_64.a
run-tests: false
- name: 🍎 macOS (universal, Makefiles)
os: macos-latest
platform: macos
config-flags: -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"
artifact-name: godot-cpp-macos-universal-release.cmake
artifact-path: cmake-build/bin/libgodot-cpp.macos.template_release.universal.a
run-tests: false
- name: 🤖 Android (arm64, Ninja)
os: ubuntu-22.04
platform: android
config-flags:
-G Ninja -DCMAKE_BUILD_TYPE=Release
--toolchain ${ANDROID_HOME}/ndk/28.1.13356709/build/cmake/android.toolchain.cmake
-DANDROID_PLATFORM=24 -DANDROID_ABI=arm64-v8a
artifact-name: godot-cpp-android-arm64-release.cmake
artifact-path: cmake-build/bin/libgodot-cpp.android.template_release.arm64.a
flags: arch=arm64
run-tests: false
- name: 🍏 iOS (arm64, XCode)
os: macos-latest
platform: ios
config-flags:
-G Xcode
--toolchain cmake/ios.toolchain.cmake
-DPLATFORM=OS64
build-flags: --config Release
artifact-name: godot-cpp-ios-arm64-release.cmake
artifact-path: cmake-build/bin/libgodot-cpp.ios.template_release.arm64.a
flags: arch=arm64
run-tests: false
- name: 🌐 Web (wasm32, Ninja)
os: ubuntu-22.04
platform: web
config-flags:
-G Ninja -DCMAKE_BUILD_TYPE=Release
--toolchain ${EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake
artifact-name: godot-cpp-web-wasm32-release.cmake
artifact-path: cmake-build/bin/libgodot-cpp.web.template_release.wasm32.a
run-tests: false
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Run sccache-cache
uses: mozilla-actions/sccache-action@v0.0.9
- name: Setup godot-cpp
uses: ./.github/actions/setup-godot-cpp
with:
platform: ${{ matrix.platform }}
windows-compiler: ${{ matrix.compiler }}
buildtool: cmake
- name: Configure godot-cpp-test with template_debug
run: >
cmake --log-level=VERBOSE -S . -B cmake-build ${{ env.config-flags }} ${{ matrix.config-flags }}
- name: Build godot-cpp-test (template_debug)
run: >
cmake --build cmake-build --verbose --target godot-cpp-test ${{ matrix.build-flags }}
- name: Configure godot-cpp-test with template_release
run: >
cmake --fresh --log-level=VERBOSE -S . -B cmake-build
-DGODOTCPP_TARGET=template_release ${{ env.config-flags }} ${{ matrix.config-flags }}
- name: Build godot-cpp-test (template_release)
run: >
cmake --build cmake-build --verbose --target godot-cpp-test ${{ matrix.build-flags }}
- name: Run sccache stat for check
shell: bash
run: ${SCCACHE_PATH} --show-stats
- name: Download latest Godot artifacts
uses: dsnopek/action-download-artifact@1322f74e2dac9feed2ee76a32d9ae1ca3b4cf4e9
if: matrix.run-tests && env.GODOT_TEST_VERSION == 'master'
with:
repo: godotengine/godot
branch: master
event: push
workflow: linux_builds.yml
workflow_conclusion: success
name: linux-editor-mono
search_artifacts: true
check_artifacts: true
ensure_latest: true
path: godot-artifacts
- name: Prepare Godot artifacts for testing
if: matrix.run-tests && env.GODOT_TEST_VERSION == 'master'
run: |
chmod +x ./godot-artifacts/godot.linuxbsd.editor.x86_64.mono
echo "GODOT=$(pwd)/godot-artifacts/godot.linuxbsd.editor.x86_64.mono" >> $GITHUB_ENV
- name: Download requested Godot version for testing
if: matrix.run-tests && env.GODOT_TEST_VERSION != 'master'
run: |
wget "https://github.com/godotengine/godot-builds/releases/download/${GODOT_TEST_VERSION}/Godot_v${GODOT_TEST_VERSION}_linux.x86_64.zip" -O Godot.zip
unzip -a Godot.zip
chmod +x "Godot_v${GODOT_TEST_VERSION}_linux.x86_64"
echo "GODOT=$(pwd)/Godot_v${GODOT_TEST_VERSION}_linux.x86_64" >> $GITHUB_ENV
- name: Run tests
if: matrix.run-tests
run: |
$GODOT --headless --version
cd test
# Need to run the editor so .godot is generated... but it crashes! Ignore that :-)
(cd project && (timeout 30 $GODOT --import --headless >/dev/null 2>&1 || true))
./run-tests.sh
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact-name }}
path: ${{ matrix.artifact-path }}
if-no-files-found: error

View File

@@ -6,19 +6,14 @@ env:
# Only used for the cache key. Increment version to force clean build.
GODOT_BASE_BRANCH: master
# Used to select the version of Godot to run the tests with.
GODOT_TEST_VERSION: master
# Use UTF-8 on Linux.
LANG: en_US.UTF-8
LC_ALL: en_US.UTF-8
# Use UTF-8 on Windows.
PYTHONIOENCODING: utf8
GODOT_TEST_VERSION: 4.3-stable
concurrency:
group: ci-scons-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-scons:
build:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
@@ -33,6 +28,15 @@ jobs:
run-tests: true
cache-name: linux-x86_64
- name: 🐧 Linux (GCC, Double Precision)
os: ubuntu-22.04
platform: linux
artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release
artifact-path: bin/libgodot-cpp.linux.template_release.double.x86_64.a
flags: precision=double
run-tests: false
cache-name: linux-x86_64-f64
- name: 🏁 Windows (x86_64, MSVC)
os: windows-2022
platform: windows
@@ -106,7 +110,6 @@ jobs:
with:
platform: ${{ matrix.platform }}
windows-compiler: ${{ contains(matrix.flags, 'use_mingw=yes') && 'mingw' || 'msvc' }}
buildtool: scons
- name: Generate godot-cpp sources only
run: |
@@ -177,3 +180,70 @@ jobs:
name: ${{ matrix.artifact-name }}
path: ${{ matrix.artifact-path }}
if-no-files-found: error
linux-cmake:
name: 🐧 Build (Linux, GCC, CMake)
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -qqq build-essential pkg-config cmake
- name: Build godot-cpp
run: |
cmake -DCMAKE_BUILD_TYPE=Release .
make -j $(nproc) VERBOSE=1
- name: Build test GDExtension library
run: |
cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." .
make -j $(nproc) VERBOSE=1
linux-cmake-ninja:
name: 🐧 Build (Linux, GCC, CMake Ninja)
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -qqq build-essential pkg-config cmake ninja-build
- name: Build godot-cpp
run: |
cmake -DCMAKE_BUILD_TYPE=Release -GNinja .
cmake --build . -j $(nproc) --verbose
- name: Build test GDExtension library
run: |
cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -GNinja .
cmake --build . -j $(nproc) --verbose
windows-msvc-cmake:
name: 🏁 Build (Windows, MSVC, CMake)
runs-on: windows-2022
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build godot-cpp
run: |
cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 17 2022" .
cmake --build . --verbose --config Release
- name: Build test GDExtension library
run: |
cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -G"Visual Studio 17 2022" .
cmake --build . --verbose --config Release

View File

@@ -9,58 +9,13 @@ jobs:
# First stage: Only static checks, fast and prevent expensive builds from running.
static-checks:
name: 📊 Static Checks
if: '!vars.DISABLE_GODOT_CI'
name: 📊 Static Checks
uses: ./.github/workflows/static_checks.yml
# Second stage: Review code changes
changes:
name: Analyze Changes
# Second stage: Run all the builds and some of the tests.
ci:
name: 🛠️ Continuous Integration
needs: static-checks
runs-on: ubuntu-latest
outputs:
sources: ${{ steps.filter.outputs.sources_any_changed }}
scons: ${{ steps.filter.outputs.scons_any_changed }}
cmake: ${{ steps.filter.outputs.cmake_any_changed }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: tj-actions/changed-files@v45
id: filter
with:
files_yaml: |
sources:
- '.github/workflows/*.yml'
- '**/*.py'
- '**/*.cpp'
- '**/*.hpp'
- '**/*.h'
- '**/*.inc'
- 'test/build_profile.json'
- 'gdextension/extension_api.json'
scons:
- '**/SConstruct'
- '**/SCsub'
cmake:
- '**/CMakeLists.txt'
- '**/*.cmake'
- name: echo sources changed
run: |
echo sources ${{ steps.filter.outputs.sources_any_modified }}
echo scons ${{ steps.filter.outputs.scons_any_modified }}
echo cmake ${{ steps.filter.outputs.cmake_any_modified }}
# Third stage: Run all the builds and some of the tests.
ci-scons:
name: 🛠️ SCons CI
needs: changes
if: ${{ needs.changes.outputs.scons == 'true' || needs.changes.outputs.sources == 'true' }}
uses: ./.github/workflows/ci-scons.yml
ci-cmake:
name: 🛠️ CMake CI
needs: changes
if: ${{ needs.changes.outputs.cmake == 'true' || needs.changes.outputs.sources == 'true' }}
uses: ./.github/workflows/ci-cmake.yml
uses: ./.github/workflows/ci.yml

View File

@@ -17,13 +17,21 @@ jobs:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v45
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [ "${{ github.event_name }}" == "pull_request" ]; then
files=$(git diff-tree --no-commit-id --name-only -r HEAD^1..HEAD 2> /dev/null || true)
elif [ "${{ github.event_name }}" == "push" -a "${{ github.event.forced }}" == "false" -a "${{ github.event.created }}" == "false" ]; then
files=$(git diff-tree --no-commit-id --name-only -r ${{ github.event.before }}..${{ github.event.after }} 2> /dev/null || true)
fi
files=$(echo "$files" | grep -v 'thirdparty' | xargs -I {} sh -c 'echo "\"./{}\""' | tr '\n' ' ')
echo "CHANGED_FILES=$files" >> $GITHUB_ENV
- name: Style checks via pre-commit
uses: pre-commit/action@v3.0.1
with:
extra_args: --verbose --hook-stage manual --files ${{ steps.changed-files.outputs.all_changed_files }}
extra_args: --verbose --hook-stage manual --files ${{ env.CHANGED_FILES }}
- name: Check generated files consistency
run:

5
.gitignore vendored
View File

@@ -198,7 +198,4 @@ venv
# Clion Configuration
.idea/
cmake-build*/
# CMake related
CMakeUserPresets.json
cmake-build-*

View File

@@ -9,40 +9,30 @@ exclude: |
repos:
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v20.1.0
rev: v17.0.6
hooks:
- id: clang-format
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.4
rev: v0.4.4
hooks:
- id: ruff
args: [--fix]
files: (\.py|SConstruct)$
types_or: [text]
- id: ruff-format
files: (\.py|SConstruct)$
types_or: [text]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.14.1 # Latest version that supports Python 3.8
rev: v0.971
hooks:
- id: mypy
files: \.py$
types_or: [text]
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
rev: v2.3.0
hooks:
- id: codespell
additional_dependencies: [tomli]
- repo: https://github.com/BlankSpruce/gersemi
rev: 0.19.2
hooks:
- id: gersemi
args: ["-i", "--no-warn-about-unknown-commands", "-l", "120"]
- repo: local
hooks:
- id: copyright-headers

View File

@@ -1,74 +1,24 @@
cmake_minimum_required(VERSION 3.10...3.17)
cmake_minimum_required(VERSION 3.13)
project(godot-cpp LANGUAGES CXX)
#[=======================================================================[.rst:
# Configure CMake
# https://discourse.cmake.org/t/how-do-i-remove-compile-options-from-target/5965
# https://stackoverflow.com/questions/74426638/how-to-remove-rtc1-from-specific-target-or-file-in-cmake
if(${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
STRING(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
endif ()
endif ()
CMake Version requirements
--------------------------
include( ${PROJECT_SOURCE_DIR}/cmake/godotcpp.cmake )
To enable use of the emscripten emsdk hack for pseudo shared library support
without polluting options for consumers we need to use the
CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE which was introduced in version 3.17
# I know this doesn't look like a typical CMakeLists.txt, but as we are
# attempting mostly feature parity with SCons, and easy maintenance, the closer
# the two build systems look the easier they will be to keep in lockstep.
For more information check cmake/emsdkHack.cmake
SCons Compatibility
-------------------
There is an understandable conflict between build systems as they define
similar concepts in different ways. When there isn't a 1:1 relationship,
compromises need to be made to resolve those differences.
As we are attempting to maintain feature parity, and ease of maintenance, these
CMake scripts are built to resemble the SCons build system wherever possible.
Where they are not, we will attempt to document common difference in
doc/cmake.rst and platform specific differences in their respective
cmake/<platform>.cmake file.
The file structure and file content are made to match, if not in content then
in spirit. The closer the two build systems look the easier they will be to
maintain.
Where the SCons additional scripts in the tools directory, The CMake scripts
are in the cmake directory.
For example; the tools/godotcpp.py is matched by the cmake/godotcpp.cmake file
.. highlight:: python
cpp_tool = Tool("godotcpp", toolpath=["tools"])
cpp_tool.options(opts, env)
The CMake equivalent is below.
]=======================================================================]
include(cmake/godotcpp.cmake)
# The typical target definitions are in ${PROJECT_SOURCE_DIR}/cmake/godotcpp.cmake
godotcpp_options()
#[[ People are compiling godot by itself and expecting template_debug
Replace this with PROJECT_IS_TOP_LEVEL, <PROJECT-NAME>_IS_TOP_LEVEL when minimum reaches 3.21
]]
if(NOT PROJECT_NAME)
set(GODOTCPP_IS_TOP_LEVEL ON)
endif()
# Define our project.
project(
godot-cpp
VERSION 4.4
DESCRIPTION "C++ bindings for the Godot Engine's GDExtensions API."
HOMEPAGE_URL "https://github.com/godotengine/godot-cpp"
LANGUAGES CXX
)
compiler_detection()
godotcpp_generate()
# Conditionally enable the godot-cpp.test.<target> integration testing targets
if(GODOTCPP_ENABLE_TESTING)
add_subdirectory(test)
endif()
#[[ If this is the top level CMakeLists.txt, Generators which honor the
USE_FOLDERS flag will organize godot-cpp targets under a subfolder named
'godot-cpp'. This is enable by default from CMake version 3.26 ]]
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

View File

@@ -1,14 +1,9 @@
#!/usr/bin/env python
import os
import sys
# Add godot-cpp folder to sys.path, so that we can import local modules.
sys.path.append(Dir(".").srcnode().abspath)
EnsureSConsVersion(4, 0)
EnsurePythonVersion(3, 8)
try:
Import("env")
@@ -32,7 +27,7 @@ if profile:
elif os.path.isfile(profile + ".py"):
customs.append(profile + ".py")
opts = Variables(customs, ARGUMENTS)
cpp_tool = Tool("godotcpp", toolpath=[Dir("tools").srcnode().abspath])
cpp_tool = Tool("godotcpp", toolpath=["tools"])
cpp_tool.options(opts, env)
opts.Update(env)

File diff suppressed because it is too large Load Diff

View File

@@ -1,176 +0,0 @@
#[=======================================================================[.rst:
GodotCPPModule.cmake
---------------------
This file contains functions and tests which may be needed by consumers.
* Generate Trimmed API
* Generate File List
* Generate Bindings
If you want to use these functions in your project extend the CMAKE_MODULE_PATH
by adding these two lines into your CMakeLists.txt after the inclusion
godot-cpp
.. highlight:: cmake
list(APPEND CMAKE_MODULE_PATH "${godot-cpp_SOURCE_DIR}/cmake")
include( GodotCPPModule )
]=======================================================================]
find_package(Python3 3.4 REQUIRED) # pathlib should be present
#[[ Generate Trimmed API
The build_profile.py has a __main__ and is used as a tool
Its usage is listed as:
$ python build_profile.py BUILD_PROFILE INPUT_JSON [OUTPUT_JSON]
]]
function(build_profile_generate_trimmed_api BUILD_PROFILE INPUT_JSON OUTPUT_JSON)
execute_process(
COMMAND
"${Python3_EXECUTABLE}" "${godot-cpp_SOURCE_DIR}/build_profile.py" "${BUILD_PROFILE}" "${INPUT_JSON}"
"${OUTPUT_JSON}"
WORKING_DIRECTORY ${godot-cpp_SOURCE_DIR}
)
endfunction()
#[[ Generate File List
Use the binding_generator.py Python script to determine the list of files that
will be passed to the code generator using extension_api.json.
NOTE: This happens for every configure.]]
function(binding_generator_get_file_list OUT_VAR_NAME API_FILEPATH OUTPUT_DIR)
# This code snippet will be squashed into a single line
# The two strings make this a list, in CMake lists are semicolon delimited strings.
set(PYTHON_SCRIPT
"from binding_generator import print_file_list"
"print_file_list( api_filepath='${API_FILEPATH}',
output_dir='${OUTPUT_DIR}',
headers=True,
sources=True)"
)
message(DEBUG "Python:\n${PYTHON_SCRIPT}")
# Strip newlines and whitespace to make it a one-liner.
string(REGEX REPLACE "\n *" " " PYTHON_SCRIPT "${PYTHON_SCRIPT}")
execute_process(
COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
WORKING_DIRECTORY "${godot-cpp_SOURCE_DIR}"
OUTPUT_VARIABLE GENERATED_FILES_LIST
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Debug output
message(DEBUG "FileList-Begin")
foreach(PATH ${GENERATED_FILES_LIST})
message(DEBUG ${PATH})
endforeach()
# Error out if the file list generator returned no files.
list(LENGTH GENERATED_FILES_LIST LIST_LENGTH)
if(NOT LIST_LENGTH GREATER 0)
message(FATAL_ERROR "File List Generation Failed")
endif()
message(STATUS "There are ${LIST_LENGTH} Files to generate")
set(${OUT_VAR_NAME} ${GENERATED_FILES_LIST} PARENT_SCOPE)
endfunction()
#[[ Generate Bindings
Using the generated file list, use the binding_generator.py to generate the
godot-cpp bindings. This will run at build time only if there are files
missing. ]]
function(
binding_generator_generate_bindings
API_FILE
USE_TEMPLATE_GET_NODE
BITS
PRECISION
OUTPUT_DIR
)
# This code snippet will be squashed into a single line
set(PYTHON_SCRIPT
"from binding_generator import generate_bindings"
"generate_bindings(
api_filepath='${API_FILE}',
use_template_get_node='${USE_TEMPLATE_GET_NODE}',
bits='${BITS}',
precision='${PRECISION}',
output_dir='${OUTPUT_DIR}')"
)
message(DEBUG "Python:\n${PYTHON_SCRIPT}")
# Strip newlines and whitespace to make it a one-liner.
string(REGEX REPLACE "\n *" " " PYTHON_SCRIPT "${PYTHON_SCRIPT}")
add_custom_command(
OUTPUT ${GENERATED_FILES_LIST}
COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
VERBATIM
WORKING_DIRECTORY ${godot-cpp_SOURCE_DIR}
MAIN_DEPENDENCY ${GODOTCPP_GDEXTENSION_API_FILE}
DEPENDS ${godot-cpp_SOURCE_DIR}/binding_generator.py
COMMENT "Generating bindings"
)
add_custom_target(generate_bindings DEPENDS ${GENERATED_FILES_LIST})
set_target_properties(generate_bindings PROPERTIES FOLDER "godot-cpp")
endfunction()
#[[ Generate doc_data.cpp
The documentation displayed in the Godot editor is compiled into the extension.
It takes a list of XML source files, and transforms them into a cpp file that
is added to the sources list.]]
function(generate_doc_source OUTPUT_PATH SOURCES)
# Transform SOURCES CMake LIST
# quote each path with ''
# join with , to transform into a python list minus the surrounding []
set(PYTHON_LIST "${SOURCES}")
list(TRANSFORM PYTHON_LIST REPLACE "(.*\.xml)" "'\\1'")
list(JOIN PYTHON_LIST "," PYTHON_LIST)
get_filename_component(OUTPUT_DIR "${OUTPUT_PATH}" DIRECTORY)
file(MAKE_DIRECTORY ${OUTPUT_DIR})
# Python one-liner to run our command
# lists in CMake are just strings delimited by ';', so this works.
set(PYTHON_SCRIPT
"from doc_source_generator import generate_doc_source"
"generate_doc_source( '${OUTPUT_PATH}', [${PYTHON_LIST}] )"
)
add_custom_command(
OUTPUT "${OUTPUT_PATH}"
COMMAND "${Python3_EXECUTABLE}" "-c" "${PYTHON_SCRIPT}"
VERBATIM
WORKING_DIRECTORY "${godot-cpp_SOURCE_DIR}"
DEPENDS #
"${godot-cpp_SOURCE_DIR}/doc_source_generator.py"
"${SOURCES}"
COMMENT "Generating: ${OUTPUT_PATH}"
)
add_custom_target(generate_doc_source DEPENDS "${OUTPUT_PATH}")
set_target_properties(generate_doc_source PROPERTIES FOLDER "godot-cpp")
endfunction()
#[[ target_doc_sources
A simpler interface to add xml files as doc source to a output target.
TARGET: The gdexension library target
SOURCES: a list of xml files to use for source generation and inclusion.]]
function(target_doc_sources TARGET SOURCES)
# set the generated file name
set(DOC_SOURCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/gen/doc_source.cpp")
# Create the file generation target, this won't be triggered unless a target
# that depends on DOC_SOURCE_FILE is built
generate_doc_source( "${DOC_SOURCE_FILE}" ${SOURCES} )
# Add DOC_SOURCE_FILE as a dependency to TARGET
target_sources(${TARGET} PRIVATE "${DOC_SOURCE_FILE}")
# Without adding this dependency to the doc_source_generator, XCode will complain.
add_dependencies(${TARGET} generate_doc_source)
endfunction()

View File

@@ -1,49 +0,0 @@
#[=======================================================================[.rst:
Android
-------
This file contains functions for options and configuration for targeting the
Android platform
Configuration of the Android toolchain is done using toolchain files,
CMakePresets, or variables on the command line.
The `Android SDK`_ provides toolchain files to help with configuration.
CMake has its own `built-in support`_ for cross compiling to the
Android platforms.
.. warning::
Android does not support or test the CMake built-in workflow, recommend
using their toolchain file.
.. _Android SDK:https://developer.android.com/ndk/guides/cmake
.. _built-in support:https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android
There is further information and examples in the doc/cmake.rst file.
]=======================================================================]
#[============================[ Android Options ]============================]
function(android_options)
#[[ Options from SCons
The options below are managed by CMake toolchain files, doc.cmake.rst has
more information
android_api_level : Target Android API level.
Default = 24
ANDROID_HOME : Path to your Android SDK installation.
Default = os.environ.get("ANDROID_HOME", os.environ.get("ANDROID_SDK_ROOT")
]]
endfunction()
#[===========================[ Target Generation ]===========================]
function(android_generate)
target_compile_definitions(godot-cpp PUBLIC ANDROID_ENABLED UNIX_ENABLED)
common_compiler_flags()
endfunction()

View File

@@ -1,192 +1,94 @@
#[=======================================================================[.rst:
Common Compiler Flags
---------------------
# Add warnings based on compiler & version
# Set some helper variables for readability
set( compiler_less_than_v8 "$<VERSION_LESS:$<CXX_COMPILER_VERSION>,8>" )
set( compiler_greater_than_or_equal_v9 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,9>" )
set( compiler_greater_than_or_equal_v11 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,11>" )
set( compiler_less_than_v11 "$<VERSION_LESS:$<CXX_COMPILER_VERSION>,11>" )
set( compiler_greater_than_or_equal_v12 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,12>" )
This file contains host platform toolchain and target platform agnostic
configuration. It includes flags like optimization levels, warnings, and
features. For target platform specific flags look to each of the
``cmake/<platform>.cmake`` files.
# These compiler options reflect what is in godot/SConstruct.
target_compile_options( ${PROJECT_NAME} PRIVATE
# MSVC only
$<${compiler_is_msvc}:
/W4
The default compile and link options CMake adds can be found in the
platform modules_. When a project is created it initializes its variables from
the ``CMAKE_*`` values. The cleanest way I have found to alter these defaults
is the use of the ``CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE`` as demonstrated by
the emsdkHack.cmake to overcome the limitation on shared library creation.
# Disable warnings which we don't plan to fix.
/wd4100 # C4100 (unreferenced formal parameter): Doesn't play nice with polymorphism.
/wd4127 # C4127 (conditional expression is constant)
/wd4201 # C4201 (non-standard nameless struct/union): Only relevant for C89.
/wd4244 # C4244 C4245 C4267 (narrowing conversions): Unavoidable at this scale.
/wd4245
/wd4267
/wd4305 # C4305 (truncation): double to float or real_t, too hard to avoid.
/wd4514 # C4514 (unreferenced inline function has been removed)
/wd4714 # C4714 (function marked as __forceinline not inlined)
/wd4820 # C4820 (padding added after construct)
>
So far the emsdkHack is the only modification to the defaults we have made.
# Clang and GNU common options
$<$<OR:${compiler_is_clang},${compiler_is_gnu}>:
-Wall
-Wctor-dtor-privacy
-Wextra
-Wno-unused-parameter
-Wnon-virtual-dtor
-Wwrite-strings
>
.. _modules: https://github.com/Kitware/CMake/blob/master/Modules/Platform/
# Clang only
$<${compiler_is_clang}:
-Wimplicit-fallthrough
-Wno-ordered-compare-function-pointers
>
]=======================================================================]
# GNU only
$<${compiler_is_gnu}:
-Walloc-zero
-Wduplicated-branches
-Wduplicated-cond
-Wno-misleading-indentation
-Wplacement-new=1
-Wshadow-local
-Wstringop-overflow=4
>
$<$<AND:${compiler_is_gnu},${compiler_less_than_v8}>:
# Bogus warning fixed in 8+.
-Wno-strict-overflow
>
$<$<AND:${compiler_is_gnu},${compiler_greater_than_or_equal_v9}>:
-Wattribute-alias=2
>
$<$<AND:${compiler_is_gnu},${compiler_greater_than_or_equal_v11}>:
# Broke on MethodBind templates before GCC 11.
-Wlogical-op
>
$<$<AND:${compiler_is_gnu},${compiler_less_than_v11}>:
# Regression in GCC 9/10, spams so much in our variadic templates that we need to outright disable it.
-Wno-type-limits
>
$<$<AND:${compiler_is_gnu},${compiler_greater_than_or_equal_v12}>:
# False positives in our error macros, see GH-58747.
-Wno-return-type
>
)
#[[ Compiler Configuration, not to be confused with build targets ]]
set(DEBUG_SYMBOLS "$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>")
#[[ Compiler Identification ]]
set(IS_CLANG "$<CXX_COMPILER_ID:Clang>")
set(IS_APPLECLANG "$<CXX_COMPILER_ID:AppleClang>")
set(IS_GNU "$<CXX_COMPILER_ID:GNU>")
set(IS_MSVC "$<CXX_COMPILER_ID:MSVC>")
set(NOT_MSVC "$<NOT:$<CXX_COMPILER_ID:MSVC>>")
set(LT_V8 "$<VERSION_LESS:$<CXX_COMPILER_VERSION>,8>")
set(GE_V9 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,9>")
set(GT_V11 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,11>")
set(LT_V11 "$<VERSION_LESS:$<CXX_COMPILER_VERSION>,11>")
set(GE_V12 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,12>")
#[===========================[ compiler_detection ]===========================]
#[[ Check for clang-cl with MSVC frontend
The compiler is tested and set when the project command is called.
The variable CXX_COMPILER_FRONTEND_VARIANT was introduced in 3.14
The generator expression $<CXX_COMPILER_FRONTEND_VARIANT> wasn't introduced
until CMake 3.30 so we can't use it yet.
So to support clang downloaded from llvm.org which uses the MSVC frontend
by default, we need to test for it. ]]
function(compiler_detection)
if(${CMAKE_CXX_COMPILER_ID} STREQUAL Clang)
if(${CMAKE_CXX_COMPILER_FRONTEND_VARIANT} STREQUAL MSVC)
message(STATUS "Using clang-cl")
set(IS_CLANG "0" PARENT_SCOPE)
set(IS_MSVC "1" PARENT_SCOPE)
set(NOT_MSVC "0" PARENT_SCOPE)
endif()
# Treat warnings as errors
function( set_warning_as_error )
message( STATUS "[${PROJECT_NAME}] Treating warnings as errors")
if ( CMAKE_VERSION VERSION_GREATER_EQUAL "3.24" )
set_target_properties( ${PROJECT_NAME}
PROPERTIES
COMPILE_WARNING_AS_ERROR ON
)
else()
target_compile_options( ${PROJECT_NAME}
PRIVATE
$<${compiler_is_msvc}:/WX>
$<$<OR:${compiler_is_clang},${compiler_is_gnu}>:-Werror>
)
endif()
endfunction()
#[=========================[ common_compiler_flags ]=========================]
#[[ This function assumes it is being called from within one of the platform
generate functions, with all the variables from lower scopes defined. ]]
function(common_compiler_flags)
# gersemi: off
# These compiler options reflect what is in godot/SConstruct.
target_compile_options(
godot-cpp
# The public flag tells CMake that the following options are transient,
# and will propagate to consumers.
PUBLIC
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
# saves around 20% of binary size and very significant build time.
$<${DISABLE_EXCEPTIONS}:$<${NOT_MSVC}:-fno-exceptions>>
# Enabling Debug Symbols
$<${DEBUG_SYMBOLS}:
# Adding dwarf-4 explicitly makes stacktraces work with clang builds,
# otherwise addr2line doesn't understand them.
$<${NOT_MSVC}:
-gdwarf-4
$<IF:${IS_DEV_BUILD},-g3,-g2>
>
>
$<${IS_DEV_BUILD}:$<${NOT_MSVC}:-fno-omit-frame-pointer -O0>>
$<${HOT_RELOAD}:$<${IS_GNU}:-fno-gnu-unique>>
# MSVC only
$<${IS_MSVC}:
# /MP isn't valid for clang-cl with msvc frontend
$<$<CXX_COMPILER_ID:MSVC>:/MP${PROC_N}>
# Interpret source files as utf-8
/utf-8
>
# Warnings below, these do not need to propagate to consumers.
PRIVATE
$<${IS_MSVC}:
/W4 # Warning level 4 (informational) warnings that aren't off by default.
# Disable warnings which we don't plan to fix.
/wd4100 # C4100 (unreferenced formal parameter): Doesn't play nice with polymorphism.
/wd4127 # C4127 (conditional expression is constant)
/wd4201 # C4201 (non-standard nameless struct/union): Only relevant for C89.
/wd4244 # C4244 C4245 C4267 (narrowing conversions): Unavoidable at this scale.
/wd4245
/wd4267
/wd4305 # C4305 (truncation): double to float or real_t, too hard to avoid.
/wd4514 # C4514 (unreferenced inline function has been removed)
/wd4714 # C4714 (function marked as __forceinline not inlined)
/wd4820 # C4820 (padding added after construct)
>
# Clang and GNU common options
$<$<OR:${IS_CLANG},${IS_GNU}>:
-Wall
-Wctor-dtor-privacy
-Wextra
-Wno-unused-parameter
-Wnon-virtual-dtor
-Wwrite-strings
>
# Clang only
$<${IS_CLANG}:
-Wimplicit-fallthrough
-Wno-ordered-compare-function-pointers
>
# GNU only
$<${IS_GNU}:
-Walloc-zero
-Wduplicated-branches
-Wduplicated-cond
-Wno-misleading-indentation
-Wplacement-new=1
-Wshadow-local
-Wstringop-overflow=4
# Bogus warning fixed in 8+.
$<${LT_V8}:-Wno-strict-overflow>
$<${GE_V9}:-Wattribute-alias=2>
# Broke on MethodBind templates before GCC 11.
$<${GT_V11}:-Wlogical-op>
# Regression in GCC 9/10, spams so much in our variadic templates that we need to outright disable it.
$<${LT_V11}:-Wno-type-limits>
# False positives in our error macros, see GH-58747.
$<${GE_V12}:-Wno-return-type>
>
)
target_compile_definitions(
godot-cpp
PUBLIC
GDEXTENSION
# features
$<${DEBUG_FEATURES}:DEBUG_ENABLED>
$<${IS_DEV_BUILD}:DEV_ENABLED>
$<${HOT_RELOAD}:HOT_RELOAD_ENABLED>
$<$<STREQUAL:${GODOTCPP_PRECISION},double>:REAL_T_IS_DOUBLE>
$<${IS_MSVC}:$<${DISABLE_EXCEPTIONS}:_HAS_EXCEPTIONS=0>>
$<${THREADS_ENABLED}:THREADS_ENABLED>
)
target_link_options(
godot-cpp
PUBLIC
$<${DEBUG_SYMBOLS}:$<${IS_MSVC}:/DEBUG:FULL>>
$<$<NOT:${DEBUG_SYMBOLS}>:
$<${IS_GNU}:-s>
$<${IS_CLANG}:-s>
$<${IS_APPLECLANG}:-Wl,-S -Wl,-x -Wl,-dead_strip>
>
PRIVATE
$<${IS_MSVC}:
/WX # treat link warnings as errors.
/MANIFEST:NO # We dont need a manifest
>
)
# gersemi: on
endfunction()
if ( GODOT_WARNING_AS_ERROR )
set_warning_as_error()
endif()

View File

@@ -1,40 +0,0 @@
#[=======================================================================[.rst:
emsdkHack
---------
The Emscripten platform doesn't support the use of shared libraries as known by cmake.
* https://github.com/emscripten-core/emscripten/issues/15276
* https://github.com/emscripten-core/emscripten/issues/17804
This workaround only works due to the way the cmake scripts are loaded.
Prior to the use of ``project( ... )`` directive we need to set
``CMAKE_PROJECT_INCLUDE=cmake/emscripten.cmake``.
This file will be loaded after the toolchain overriding the settings that
prevent shared library building.
CMAKE_PROJECT_INCLUDE was Added in version 3.15.
``CMAKE_PROJECT_<projectName>_INCLUDE`` was Added in version 3.17:
More information on cmake's `code injection`_
.. _code injection:https://cmake.org/cmake/help/latest/command/project.html#code-injection
Overwrite Shared Library Properties to allow shared libs to be generated.
]=======================================================================]
if(EMSCRIPTEN)
set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-sSIDE_MODULE=1")
set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-sSIDE_MODULE=1")
set(CMAKE_SHARED_LIBRARY_SUFFIX) # remove the suffix from the shared lib
set(CMAKE_STRIP FALSE) # used by default in pybind11 on .so modules
# The Emscripten toolchain sets the default value for EMSCRIPTEN_SYSTEM_PROCESSOR to x86
# and copies that to CMAKE_SYSTEM_PROCESSOR. We don't want that.
set(CMAKE_SYSTEM_PROCESSOR "wasm32")
# the above prevents the need for logic like:
#if( ${CMAKE_SYSTEM_NAME} STREQUAL Emscripten )
# set( SYSTEM_ARCH wasm32 )
#endif ()
endif()

View File

@@ -1,399 +1,240 @@
#[=======================================================================[.rst:
godotcpp.cmake
--------------
function( godotcpp_options )
As godot-cpp is a C++ project, there are no C files, and detection of a C
compiler is unnecessary. When CMake performs the configure process, if a
C compiler is specified, like in a toolchain, or from an IDE, then it will
print a warning stating that the CMAKE_C_COMPILER compiler is unused.
This if statement simply silences that warning.
]=======================================================================]
if(CMAKE_C_COMPILER)
endif()
#[[ Include Platform Files
Because these files are included into the top level CMakeLists.txt before the
project directive, it means that
CMAKE_CURRENT_SOURCE_DIR is the location of godot-cpp's CMakeLists.txt
CMAKE_SOURCE_DIR is the location where any prior project() directive was ]]
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GodotCPPModule.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/common_compiler_flags.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/android.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/ios.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/linux.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/web.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows.cmake)
# Detect number of processors
include(ProcessorCount)
ProcessorCount(PROC_MAX)
message(STATUS "Auto-detected ${PROC_MAX} CPU cores available for build parallelism.")
# List of known platforms
set(PLATFORM_LIST
linux
macos
windows
android
ios
web
)
# List of known architectures
set(ARCH_LIST
x86_32
x86_64
arm32
arm64
rv64
ppc32
ppc64
wasm32
)
#[=============================[ godot_arch_name ]=============================]
#[[ Function to map CMAKE_SYSTEM_PROCESSOR names to godot arch equivalents ]]
function(godot_arch_name OUTVAR)
# Special case for macos universal builds that target both x86_64 and arm64
if(DEFINED CMAKE_OSX_ARCHITECTURES)
if("x86_64" IN_LIST CMAKE_OSX_ARCHITECTURES AND "arm64" IN_LIST CMAKE_OSX_ARCHITECTURES)
set(${OUTVAR} "universal" PARENT_SCOPE)
return()
endif()
endif()
# Direct match early out.
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" ARCH)
if(ARCH IN_LIST ARCH_LIST)
set(${OUTVAR} "${ARCH}" PARENT_SCOPE)
return()
endif()
# Known aliases
set(x86_64 "w64;amd64;x86-64")
set(arm32 "armv7;armv7-a")
set(arm64 "armv8;arm64v8;aarch64;armv8-a")
set(rv64 "rv;riscv;riscv64")
set(ppc32 "ppcle;ppc")
set(ppc64 "ppc64le")
if(ARCH IN_LIST x86_64)
set(${OUTVAR} "x86_64" PARENT_SCOPE)
elseif(ARCH IN_LIST arm32)
set(${OUTVAR} "arm32" PARENT_SCOPE)
elseif(ARCH IN_LIST arm64)
set(${OUTVAR} "arm64" PARENT_SCOPE)
elseif(ARCH IN_LIST rv64)
set(${OUTVAR} "rv64" PARENT_SCOPE)
elseif(ARCH IN_LIST ppc32)
set(${OUTVAR} "ppc32" PARENT_SCOPE)
elseif(ARCH IN_LIST ppc64)
set(${OUTVAR} "ppc64" PARENT_SCOPE)
elseif(ARCH MATCHES "86")
# Catches x86, i386, i486, i586, i686, etc.
set(${OUTVAR} "x86_32" PARENT_SCOPE)
else()
# Default value is whatever the processor is.
set(${OUTVAR} ${CMAKE_SYSTEM_PROCESSOR} PARENT_SCOPE)
endif()
endfunction()
# Function to define all the options.
function(godotcpp_options)
#NOTE: platform is managed using toolchain files.
#NOTE: arch is managed by using toolchain files.
# To create a universal build for macos, set CMAKE_OSX_ARCHITECTURES
set(GODOTCPP_TARGET
"template_debug"
CACHE STRING
"Which target to generate. valid values are: template_debug, template_release, and editor"
)
set_property(CACHE GODOTCPP_TARGET PROPERTY STRINGS "template_debug;template_release;editor")
#TODO platform
#TODO target
# Input from user for GDExtension interface header and the API JSON file
set(GODOTCPP_GDEXTENSION_DIR
"gdextension"
CACHE PATH
"Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )"
)
set(GODOTCPP_CUSTOM_API_FILE
""
CACHE FILEPATH
"Path to a custom GDExtension API JSON file (takes precedence over `GODOTCPP_GDEXTENSION_DIR`) ( /path/to/custom_api_file )"
)
set(GODOT_GDEXTENSION_DIR "gdextension" CACHE PATH
"Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )" )
set(GODOT_CUSTOM_API_FILE "" CACHE FILEPATH
"Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`) ( /path/to/custom_api_file )")
#TODO generate_bindings
option(GODOTCPP_GENERATE_TEMPLATE_GET_NODE "Generate a template version of the Node class's get_node. (ON|OFF)" ON)
option(GODOT_GENERATE_TEMPLATE_GET_NODE
"Generate a template version of the Node class's get_node. (ON|OFF)" ON)
#TODO build_library
set(GODOTCPP_PRECISION "single" CACHE STRING "Set the floating-point precision level (single|double)")
set(GODOTCPP_THREADS ON CACHE BOOL "Enable threading support")
set(GODOT_PRECISION "single" CACHE STRING
"Set the floating-point precision level (single|double)")
#TODO arch
#TODO threads
#TODO compiledb
#TODO compiledb_file
#TODO build_profile aka cmake preset
set(GODOTCPP_BUILD_PROFILE "" CACHE PATH "Path to a file containing a feature build profile")
set(GODOT_USE_HOT_RELOAD "" CACHE BOOL
"Enable the extra accounting required to support hot reload. (ON|OFF)")
set(GODOTCPP_USE_HOT_RELOAD "" CACHE BOOL "Enable the extra accounting required to support hot reload. (ON|OFF)")
option(GODOT_DISABLE_EXCEPTIONS "Force disabling exception handling code (ON|OFF)" ON )
set( GODOT_SYMBOL_VISIBILITY "hidden" CACHE STRING
"Symbols visibility on GNU platforms. Use 'auto' to apply the default value. (auto|visible|hidden)")
set_property( CACHE GODOT_SYMBOL_VISIBILITY PROPERTY STRINGS "auto;visible;hidden" )
#TODO optimize
#TODO debug_symbols
#TODO dev_build
# FIXME These options are not present in SCons, and perhaps should be added there.
option(GODOT_SYSTEM_HEADERS "Expose headers as SYSTEM." ON)
option(GODOT_WARNING_AS_ERROR "Treat warnings as errors" OFF)
# Run options commands on the following to populate cache for all platforms.
# This type of thing is typically done conditionally
# But as scons shows all options so shall we.
#TODO ios_options()
#TODO linux_options()
#TODO macos_options()
#TODO web_options()
#TODO windows_options()
endfunction()
function( godotcpp_generate )
# Set some helper variables for readability
set( compiler_is_clang "$<OR:$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:Clang>>" )
set( compiler_is_gnu "$<CXX_COMPILER_ID:GNU>" )
set( compiler_is_msvc "$<CXX_COMPILER_ID:MSVC>" )
# CXX_VISIBILITY_PRESET supported values are: default, hidden, protected, and internal
# which is inline with the gcc -fvisibility=
# https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html
# To match the scons options we need to change the text to match the -fvisibility flag
# it is probably worth another PR which changes both to use the flag options
if( ${GODOT_SYMBOL_VISIBILITY} STREQUAL "auto" OR ${GODOT_SYMBOL_VISIBILITY} STREQUAL "visible" )
set( GODOT_SYMBOL_VISIBILITY "default" )
endif ()
# Default build type is Debug in the SConstruct
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
set(CMAKE_BUILD_TYPE Debug)
endif()
# Hot reload is enabled by default in Debug-builds
if( GODOT_USE_HOT_RELOAD STREQUAL "" AND NOT CMAKE_BUILD_TYPE STREQUAL "Release")
set(GODOT_USE_HOT_RELOAD ON)
endif()
if(NOT DEFINED BITS)
set(BITS 32)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(BITS 64)
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
endif()
set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json")
if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "") # User-defined override.
set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}")
endif()
if ("${GODOT_PRECISION}" STREQUAL "double")
add_definitions(-DREAL_T_IS_DOUBLE)
endif()
set( GODOT_COMPILE_FLAGS )
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
set(GODOT_COMPILE_FLAGS "/utf-8") # /GF /MP
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MDd") # /Od /RTC1 /Zi
else()
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MD /O2") # /Oy /GL /Gy
endif(CMAKE_BUILD_TYPE MATCHES Debug)
add_definitions(-DNOMINMAX)
else() # GCC/Clang
if(CMAKE_BUILD_TYPE MATCHES Debug)
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-omit-frame-pointer -O0 -g")
else()
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -O3")
endif(CMAKE_BUILD_TYPE MATCHES Debug)
endif()
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
# saves around 20% of binary size and very significant build time (GH-80513).
option(GODOTCPP_DISABLE_EXCEPTIONS "Force disabling exception handling code (ON|OFF)" ON)
set(GODOTCPP_SYMBOL_VISIBILITY
"hidden"
CACHE STRING
"Symbols visibility on GNU platforms. Use 'auto' to apply the default value. (auto|visible|hidden)"
)
set_property(CACHE GODOTCPP_SYMBOL_VISIBILITY PROPERTY STRINGS "auto;visible;hidden")
#TODO optimize
option(GODOTCPP_DEV_BUILD "Developer build with dev-only debugging code (DEV_ENABLED)" OFF)
#[[ debug_symbols
Debug symbols are enabled by using the Debug or RelWithDebInfo build configurations.
Single Config Generator is set at configure time
cmake ../ -DCMAKE_BUILD_TYPE=Debug
Multi-Config Generator is set at build time
cmake --build . --config Debug
]]
# FIXME These options are not present in SCons, and perhaps should be added there.
option(GODOTCPP_SYSTEM_HEADERS "Expose headers as SYSTEM." OFF)
option(GODOTCPP_WARNING_AS_ERROR "Treat warnings as errors" OFF)
# Enable Testing
option(GODOTCPP_ENABLE_TESTING "Enable the godot-cpp.test.<target> integration testing targets" OFF)
#[[ Target Platform Options ]]
android_options()
ios_options()
linux_options()
macos_options()
web_options()
windows_options()
endfunction()
#[===========================[ Target Generation ]===========================]
function(godotcpp_generate)
#[[ Multi-Threaded MSVC Compilation
When using the MSVC compiler the build command -j <n> only specifies
parallel jobs or targets, and not multi-threaded compilation To speed up
compile times on msvc, the /MP <n> flag can be set. But we need to set it
at configure time.
MSVC is true when the compiler is some version of Microsoft Visual C++ or
another compiler simulating the Visual C++ cl command-line syntax. ]]
if(MSVC)
math(EXPR PROC_N "(${PROC_MAX}-1) | (${X}-2)>>31 & 1")
message(STATUS "Using ${PROC_N} cores for multi-threaded compilation.")
# TODO You can override it at configure time with ...." )
else()
if(CMAKE_BUILD_PARALLEL_LEVEL)
set(_cores "${CMAKE_BUILD_PARALLEL_LEVEL}")
if (GODOT_DISABLE_EXCEPTIONS)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0")
else()
set(_cores "all")
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-exceptions")
endif()
else()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc")
endif()
message(
STATUS
"Using ${_cores} cores. You can override"
" this at configure time by using -j <n> or --parallel <n> in the build"
" command."
)
message(STATUS " eg. cmake --build . -j 7 ...")
endif()
#[[ GODOTCPP_SYMBOL_VISIBLITY
To match the SCons options, the allowed values are "auto", "visible", and "hidden"
This effects the compiler flag_ -fvisibility=[default|internal|hidden|protected]
The corresponding target option CXX_VISIBILITY_PRESET accepts the compiler values.
TODO: It is probably worth a pull request which changes both to use the compiler values
.. _flag:https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fvisibility
]]
if(${GODOTCPP_SYMBOL_VISIBILITY} STREQUAL "auto" OR ${GODOTCPP_SYMBOL_VISIBILITY} STREQUAL "visible")
set(GODOTCPP_SYMBOL_VISIBILITY "default")
# Generate source from the bindings file
find_package(Python3 3.4 REQUIRED) # pathlib should be present
if(GODOT_GENERATE_TEMPLATE_GET_NODE)
set(GENERATE_BINDING_PARAMETERS "True")
else()
set(GENERATE_BINDING_PARAMETERS "False")
endif()
# Setup variable to optionally mark headers as SYSTEM
set(GODOTCPP_SYSTEM_HEADERS_ATTRIBUTE "")
if(GODOTCPP_SYSTEM_HEADERS)
set(GODOTCPP_SYSTEM_HEADERS_ATTRIBUTE SYSTEM)
endif()
#[[ Configure Binding Variables ]]
# Generate Binding Parameters (True|False)
set(USE_TEMPLATE_GET_NODE "False")
if(GODOTCPP_GENERATE_TEMPLATE_GET_NODE)
set(USE_TEMPLATE_GET_NODE "True")
endif()
# Bits (32|64)
math(EXPR BITS "${CMAKE_SIZEOF_VOID_P} * 8") # CMAKE_SIZEOF_VOID_P refers to target architecture.
# API json File
set(GODOTCPP_GDEXTENSION_API_FILE "${GODOTCPP_GDEXTENSION_DIR}/extension_api.json")
if(GODOTCPP_CUSTOM_API_FILE) # User-defined override.
set(GODOTCPP_GDEXTENSION_API_FILE "${GODOTCPP_CUSTOM_API_FILE}")
endif()
# Build Profile
if(GODOTCPP_BUILD_PROFILE)
message(STATUS "Using build profile to trim api file")
message(STATUS "\tBUILD_PROFILE = '${GODOTCPP_BUILD_PROFILE}'")
message(STATUS "\tAPI_SOURCE = '${GODOTCPP_GDEXTENSION_API_FILE}'")
build_profile_generate_trimmed_api(
"${GODOTCPP_BUILD_PROFILE}"
"${GODOTCPP_GDEXTENSION_API_FILE}"
"${CMAKE_CURRENT_BINARY_DIR}/extension_api.json"
)
set(GODOTCPP_GDEXTENSION_API_FILE "${CMAKE_CURRENT_BINARY_DIR}/extension_api.json")
endif()
message(STATUS "GODOTCPP_GDEXTENSION_API_FILE = '${GODOTCPP_GDEXTENSION_API_FILE}'")
# generate the file list to use
binding_generator_get_file_list( GENERATED_FILES_LIST
"${GODOTCPP_GDEXTENSION_API_FILE}"
"${CMAKE_CURRENT_BINARY_DIR}"
execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.print_file_list(\"${GODOT_GDEXTENSION_API_FILE}\", \"${CMAKE_CURRENT_BINARY_DIR}\", headers=True, sources=True)"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GENERATED_FILES_LIST
OUTPUT_STRIP_TRAILING_WHITESPACE
)
binding_generator_generate_bindings(
"${GODOTCPP_GDEXTENSION_API_FILE}"
"${USE_TEMPLATE_GET_NODE}"
"${BITS}"
"${GODOTCPP_PRECISION}"
"${CMAKE_CURRENT_BINARY_DIR}"
add_custom_command(OUTPUT ${GENERATED_FILES_LIST}
COMMAND "${Python3_EXECUTABLE}" "-c" "import binding_generator; binding_generator.generate_bindings(\"${GODOT_GDEXTENSION_API_FILE}\", \"${GENERATE_BINDING_PARAMETERS}\", \"${BITS}\", \"${GODOT_PRECISION}\", \"${CMAKE_CURRENT_BINARY_DIR}\")"
VERBATIM
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
MAIN_DEPENDENCY ${GODOT_GDEXTENSION_API_FILE}
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/binding_generator.py
COMMENT "Generating bindings"
)
### Platform is derived from the toolchain target
# See GeneratorExpressions PLATFORM_ID and CMAKE_SYSTEM_NAME
string(
CONCAT
SYSTEM_NAME
"$<$<PLATFORM_ID:Android>:android>"
"$<$<PLATFORM_ID:iOS>:ios>"
"$<$<PLATFORM_ID:Linux>:linux>"
"$<$<PLATFORM_ID:Darwin>:macos>"
"$<$<PLATFORM_ID:Emscripten>:web>"
"$<$<PLATFORM_ID:Windows>:windows>"
"$<$<PLATFORM_ID:Msys>:windows>"
# Get Sources
# As this cmake file was added using 'include(godotcpp)' from the root CMakeLists.txt,
# the ${CMAKE_CURRENT_SOURCE_DIR} is still the root dir.
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.c**)
file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS include/*.h**)
# Define our godot-cpp library
add_library(${PROJECT_NAME} STATIC
${SOURCES}
${HEADERS}
${GENERATED_FILES_LIST}
)
add_library(godot::cpp ALIAS ${PROJECT_NAME})
include(${PROJECT_SOURCE_DIR}/cmake/common_compiler_flags.cmake)
target_compile_features(${PROJECT_NAME}
PRIVATE
cxx_std_17
)
# Process CPU architecture argument.
godot_arch_name( ARCH_NAME )
# Transform options into generator expressions
set(HOT_RELOAD-UNSET "$<STREQUAL:${GODOTCPP_USE_HOT_RELOAD},>")
set(DISABLE_EXCEPTIONS "$<BOOL:${GODOTCPP_DISABLE_EXCEPTIONS}>")
set(THREADS_ENABLED "$<BOOL:${GODOTCPP_THREADS}>")
# GODOTCPP_DEV_BUILD
set(RELEASE_TYPES "Release;MinSizeRel")
get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(IS_MULTI_CONFIG)
message(NOTICE "=> Default build type is Debug. For other build types add --config <type> to build command")
elseif(GODOTCPP_DEV_BUILD AND CMAKE_BUILD_TYPE IN_LIST RELEASE_TYPES)
message(
WARNING
"=> GODOTCPP_DEV_BUILD implies a Debug-like build but CMAKE_BUILD_TYPE is '${CMAKE_BUILD_TYPE}'"
)
if(GODOT_USE_HOT_RELOAD)
target_compile_definitions(${PROJECT_NAME} PUBLIC HOT_RELOAD_ENABLED)
target_compile_options(${PROJECT_NAME} PUBLIC $<${compiler_is_gnu}:-fno-gnu-unique>)
endif()
set(IS_DEV_BUILD "$<BOOL:${GODOTCPP_DEV_BUILD}>")
### Define our godot-cpp library targets
# Generator Expressions that rely on the target
set(DEBUG_FEATURES "$<NOT:$<STREQUAL:${GODOTCPP_TARGET},template_release>>")
set(HOT_RELOAD "$<IF:${HOT_RELOAD-UNSET},${DEBUG_FEATURES},$<BOOL:${GODOTCPP_USE_HOT_RELOAD}>>")
# Suffix Generator Expression
string(
CONCAT
GODOTCPP_SUFFIX_GENEX
"$<1:${SYSTEM_NAME}>"
"$<1:.${GODOTCPP_TARGET}>"
"$<${IS_DEV_BUILD}:.dev>"
"$<$<STREQUAL:${GODOTCPP_PRECISION},double>:.double>"
"$<1:.${ARCH_NAME}>"
# TODO IOS_SIMULATOR
"$<$<NOT:${THREADS_ENABLED}>:.nothreads>"
)
# The same as above, but with a leading '.' to maintain backwards compatibility.
set(GODOTCPP_SUFFIX ".${GODOTCPP_SUFFIX_GENEX}")
# the godot-cpp.* library targets
add_library(godot-cpp STATIC)
# Without adding this dependency to the binding generator, XCode will complain.
add_dependencies(godot-cpp generate_bindings)
# Added for backwards compatibility with prior cmake solution so that builds dont immediately break
# from a missing target.
add_library(godot::cpp ALIAS godot-cpp)
file(GLOB_RECURSE GODOTCPP_SOURCES LIST_DIRECTORIES NO CONFIGURE_DEPENDS src/*.cpp)
target_sources(godot-cpp PRIVATE ${GODOTCPP_SOURCES} ${GENERATED_FILES_LIST})
target_include_directories(
godot-cpp
${GODOTCPP_SYSTEM_HEADERS_ATTRIBUTE}
PUBLIC include ${CMAKE_CURRENT_BINARY_DIR}/gen/include ${GODOTCPP_GDEXTENSION_DIR}
target_compile_definitions(${PROJECT_NAME} PUBLIC
$<$<CONFIG:Debug>:
DEBUG_ENABLED
DEBUG_METHODS_ENABLED
>
$<${compiler_is_msvc}:
TYPED_METHOD_BIND
>
)
# gersemi: off
set_target_properties(
godot-cpp
PROPERTIES
CXX_STANDARD 17
target_link_options(${PROJECT_NAME} PRIVATE
$<$<NOT:${compiler_is_msvc}>:
-static-libgcc
-static-libstdc++
-Wl,-R,'$$ORIGIN'
>
)
# Optionally mark headers as SYSTEM
set(GODOT_SYSTEM_HEADERS_ATTRIBUTE "")
if (GODOT_SYSTEM_HEADERS)
set(GODOT_SYSTEM_HEADERS_ATTRIBUTE SYSTEM)
endif ()
target_include_directories(${PROJECT_NAME} ${GODOT_SYSTEM_HEADERS_ATTRIBUTE} PUBLIC
include
${CMAKE_CURRENT_BINARY_DIR}/gen/include
${GODOT_GDEXTENSION_DIR}
)
# Add the compile flags
set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS ${GODOT_COMPILE_FLAGS})
# Create the correct name (godot.os.build_type.system_bits)
string(TOLOWER "${CMAKE_SYSTEM_NAME}" SYSTEM_NAME)
string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE)
if(ANDROID)
# Added the android abi after system name
set(SYSTEM_NAME ${SYSTEM_NAME}.${ANDROID_ABI})
# Android does not have the bits at the end if you look at the main godot repo build
set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}")
else()
set(OUTPUT_NAME "godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}.${BITS}")
endif()
set_target_properties(${PROJECT_NAME}
PROPERTIES
CXX_EXTENSIONS OFF
CXX_VISIBILITY_PRESET ${GODOTCPP_SYMBOL_VISIBILITY}
COMPILE_WARNING_AS_ERROR ${GODOTCPP_WARNING_AS_ERROR}
POSITION_INDEPENDENT_CODE ON
BUILD_RPATH_USE_ORIGIN ON
PREFIX "lib"
OUTPUT_NAME "${PROJECT_NAME}${GODOTCPP_SUFFIX}"
ARCHIVE_OUTPUT_DIRECTORY "$<1:${CMAKE_BINARY_DIR}/bin>"
# Things that are handy to know for dependent targets
GODOTCPP_PLATFORM "${SYSTEM_NAME}"
GODOTCPP_TARGET "${GODOTCPP_TARGET}"
GODOTCPP_ARCH "${ARCH_NAME}"
GODOTCPP_PRECISION "${GODOTCPP_PRECISION}"
GODOTCPP_SUFFIX "${GODOTCPP_SUFFIX}"
GODOTCPP_SUFFIX_GENEX "${GODOTCPP_SUFFIX_GENEX}"
# Some IDE's respect this property to logically group targets
FOLDER "godot-cpp"
CXX_VISIBILITY_PRESET ${GODOT_SYMBOL_VISIBILITY}
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin"
OUTPUT_NAME "${OUTPUT_NAME}"
)
# gersemi: on
if(CMAKE_SYSTEM_NAME STREQUAL Android)
android_generate()
elseif(CMAKE_SYSTEM_NAME STREQUAL iOS)
ios_generate()
elseif(CMAKE_SYSTEM_NAME STREQUAL Linux)
linux_generate()
elseif(CMAKE_SYSTEM_NAME STREQUAL Darwin)
macos_generate()
elseif(CMAKE_SYSTEM_NAME STREQUAL Emscripten)
web_generate()
elseif(CMAKE_SYSTEM_NAME STREQUAL Windows)
windows_generate()
endif()
endfunction()

View File

@@ -1,36 +0,0 @@
#[=======================================================================[.rst:
iOS
---
This file contains functions for options and configuration for targeting the
iOS platform
]=======================================================================]
#[==============================[ iOS Options ]==============================]
function(ios_options)
#[[ Options from SCons
TODO ios_simulator: Target iOS Simulator
Default: False
TODO ios_min_version: Target minimum iphoneos/iphonesimulator version
Default: 12.0
TODO IOS_TOOLCHAIN_PATH: Path to iOS toolchain
Default: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain",
TODO IOS_SDK_PATH: Path to the iOS SDK
Default: ''
TODO ios_triple: Triple for ios toolchain
Default: if has_ios_osxcross(): 'ios_triple' else ''
]]
endfunction()
#[===========================[ Target Generation ]===========================]
function(ios_generate)
target_compile_definitions(godot-cpp PUBLIC IOS_ENABLED UNIX_ENABLED)
common_compiler_flags()
endfunction()

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +0,0 @@
#[=======================================================================[.rst:
Linux
-----
This file contains functions for options and configuration for targeting the
Linux platform
]=======================================================================]
#[=============================[ Linux Options ]=============================]
function(linux_options)
#[[ Options from SCons
use_llvm : Use the LLVM compiler
Not implemented as compiler selection is managed by CMake. Look to
doc/cmake.rst for examples.
]]
option(GODOTCPP_USE_STATIC_CPP "Link libgcc and libstdc++ statically for better portability" ON)
endfunction()
#[===========================[ Target Generation ]===========================]
function(linux_generate)
set(STATIC_CPP "$<BOOL:${GODOTCPP_USE_STATIC_CPP}>")
target_compile_definitions(godot-cpp PUBLIC LINUX_ENABLED UNIX_ENABLED)
# gersemi: off
target_link_options(
godot-cpp
PUBLIC
$<${STATIC_CPP}:
-static-libgcc
-static-libstdc++
>
)
# gersemi: on
common_compiler_flags()
endfunction()

View File

@@ -1,41 +0,0 @@
#[=======================================================================[.rst:
MacOS
-----
This file contains functions for options and configuration for targeting the
MacOS platform
Universal Builds
----------------
To build universal binaries, ie targeting both x86_64 and arm64, use
the CMAKE_OSX_ARCHITECTURES variable prior to any project calls.
https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_ARCHITECTURES.html
]=======================================================================]
# Find Requirements
if(APPLE)
set(CMAKE_OSX_SYSROOT $ENV{SDKROOT})
endif(APPLE)
#[=============================[ MacOS Options ]=============================]
function(macos_options)
#[[ Options from SCons
TODO macos_deployment_target: macOS deployment target
Default: 'default'
TODO macos_sdk_path: macOS SDK path
Default: ''
TODO osxcross_sdk: OSXCross SDK version
Default: if has_osxcross(): "darwin16" else None
]]
endfunction()
#[===========================[ Target Generation ]===========================]
function(macos_generate)
target_compile_definitions(godot-cpp PUBLIC MACOS_ENABLED UNIX_ENABLED)
common_compiler_flags()
endfunction()

View File

@@ -1,39 +0,0 @@
#[=======================================================================[.rst:
Web
---
This file contains functions for options and configuration for targeting the
Web platform
]=======================================================================]
# Emscripten requires this hack for use of the SHARED option
set(CMAKE_PROJECT_godot-cpp_INCLUDE cmake/emsdkHack.cmake)
#[==============================[ Web Options ]==============================]
function(web_options)
endfunction()
#[===========================[ Target Generation ]===========================]
function(web_generate)
target_compile_definitions(godot-cpp PUBLIC WEB_ENABLED UNIX_ENABLED)
target_compile_options(
godot-cpp
PUBLIC #
-sSIDE_MODULE
-sSUPPORT_LONGJMP=wasm
$<${THREADS_ENABLED}:-sUSE_PTHREADS=1>
)
target_link_options(
godot-cpp
INTERFACE #
-sWASM_BIGINT
-sSUPPORT_LONGJMP=wasm
-fvisibility=hidden
-shared
)
common_compiler_flags()
endfunction()

View File

@@ -1,116 +0,0 @@
#[=======================================================================[.rst:
Windows
-------
This file contains functions for options and configuration for targeting the
Windows platform
Because this file is included into the top level CMakelists.txt before the
project directive, it means that
* ``CMAKE_CURRENT_SOURCE_DIR`` is the location of godot-cpp's CMakeLists.txt
* ``CMAKE_SOURCE_DIR`` is the location where any prior ``project(...)``
directive was
MSVC Runtime Selection
----------------------
There are two main ways to set the msvc runtime library;
Using ``target_compile_options()`` to add the flags
or using the ``CMAKE_MSVC_RUNTIME_LIBRARY`` property_ abstraction, introduced
in CMake version 3.15 with the policy CMP0091_ to remove the flags from
``CMAKE_<LANG>_FLAGS_<CONFIG>``.
Default: ``CMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$<CONFIG:Debug>:Debug>DLL"``
This initializes each target's ``MSVC_RUNTIME_LIBRARY`` property at the time of
target creation.
it is stated in the msvc_ documentation that: "All modules passed to a given
invocation of the linker must have been compiled with the same runtime library
compiler option (/MD, /MT, /LD)."
This creates a conundrum for us, the ``CMAKE_MSVC_RUNTIME_LIBRARY`` needs to be
correct at the time the target is created, but we have no control over the
consumers CMake scripts, and the per-target ``MSVC_RUNTIME_LIBRARY`` property
is not transient.
It has been raised that not using ``CMAKE_MSVC_RUNTIME_LIBRARY`` can also cause
issues_ when a dependency( independent to godot-cpp ) that doesn't set any
runtime flags, which relies purely on the ``CMAKE_MSVC_RUNTIME_LIBRARY``
variable will very likely not have the correct msvc runtime flags set.
So we'll set ``CMAKE_MSVC_RUNTIME_LIBRARY`` as CACHE STRING so that it will be
available for consumer target definitions, but also be able to be overridden if
needed.
Additionally we message consumers notifying them and pointing to this
documentation.
.. _CMP0091:https://cmake.org/cmake/help/latest/policy/CMP0091.html
.. _property:https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html
.. https://discourse.cmake.org/t/mt-staticrelease-doesnt-match-value-md-dynamicrelease/5428/4
.. _msvc: https://learn.microsoft.com/en-us/cpp/build/reference/md-mt-ld-use-run-time-library
.. _issues: https://github.com/godotengine/godot-cpp/issues/1699
]=======================================================================]
#[============================[ Windows Options ]============================]
function(windows_options)
#[[ Options from SCons
TODO silence_msvc: Silence MSVC's cl/link stdout bloat, redirecting errors to stderr
Default: True
These three options will not implemented as compiler selection is managed
by CMake toolchain files. Look to doc/cmake.rst for examples.
use_mingw: Use the MinGW compiler instead of MSVC - only effective on Windows
use_llvm: Use the LLVM compiler (MVSC or MinGW depending on the use_mingw flag
mingw_prefix: MinGW prefix
]]
option(GODOTCPP_USE_STATIC_CPP "Link MinGW/MSVC C++ runtime libraries statically" ON)
option(GODOTCPP_DEBUG_CRT "Compile with MSVC's debug CRT (/MDd)" OFF)
message(
STATUS
"If not already cached, setting CMAKE_MSVC_RUNTIME_LIBRARY.\n"
"\tFor more information please read godot-cpp/cmake/windows.cmake"
)
set(CMAKE_MSVC_RUNTIME_LIBRARY
"MultiThreaded$<IF:$<BOOL:${GODOTCPP_DEBUG_CRT}>,DebugDLL,$<$<NOT:$<BOOL:${GODOTCPP_USE_STATIC_CPP}>>:DLL>>"
CACHE STRING
"Select the MSVC runtime library for use by compilers targeting the MSVC ABI."
)
endfunction()
#[===========================[ Target Generation ]===========================]
function(windows_generate)
set(STATIC_CPP "$<BOOL:${GODOTCPP_USE_STATIC_CPP}>")
set_target_properties(godot-cpp PROPERTIES PDB_OUTPUT_DIRECTORY "$<1:${CMAKE_SOURCE_DIR}/bin>")
target_compile_definitions(
godot-cpp
PUBLIC WINDOWS_ENABLED $<${IS_MSVC}: TYPED_METHOD_BIND NOMINMAX >
)
# gersemi: off
target_link_options(
godot-cpp
PUBLIC
$<${NOT_MSVC}:
-Wl,--no-undefined
$<${STATIC_CPP}:
-static
-static-libgcc
-static-libstdc++
>
>
$<${IS_CLANG}:-lstdc++>
)
# gersemi: on
common_compiler_flags()
endfunction()

57
doc/cmake.md Normal file
View File

@@ -0,0 +1,57 @@
## CMake
### cmake arguments
`CMAKE_BUILD_TYPE`: Compilation target (Debug or Release defaults to Debug)
### godot-cpp cmake arguments
- `GODOT_GDEXTENSION_DIR`: Path to the directory containing GDExtension interface header and API JSON file
- `GODOT_SYSTEM_HEADERS`: Mark the header files as SYSTEM. This may be useful to suppress warnings in projects including this one.
- `GODOT_WARNING_AS_ERROR`: Treat any warnings as errors
- `GODOT_USE_HOT_RELOAD`: Build with hot reload support. Defaults to YES for Debug-builds and NO for Release-builds.
- `GODOT_CUSTOM_API_FILE`: Path to a custom GDExtension API JSON file (takes precedence over `gdextension_dir`)
- `GODOT_PRECISION`: Floating-point precision level ("single", "double")
### Android cmake arguments
- `CMAKE_TOOLCHAIN_FILE`: The path to the android cmake toolchain ($ANDROID_NDK/build/cmake/android.toolchain.cmake)
- `ANDROID_NDK`: The path to the android ndk root folder
- `ANDROID_TOOLCHAIN_NAME`: The android toolchain (arm-linux-androideabi-4.9 or aarch64-linux-android-4.9 or x86-4.9 or x86_64-4.9)
- `ANDROID_PLATFORM`: The android platform version (android-23)
- More info [here](https://godot.readthedocs.io/en/latest/development/compiling/compiling_for_android.html)
## Examples
```shell
Builds a debug version:
cmake .
cmake --build .
```
Builds a release version with clang
```shell
CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" .
cmake --build .
```
Builds an android armeabi-v7a debug version:
``` shell
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_NDK=$ANDROID_NDK \
-DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 -DANDROID_PLATFORM=android-23 -DCMAKE_BUILD_TYPE=Debug .
cmake --build .
```
## Protip
Generate the buildfiles in a sub directory to not clutter the root directory with build files:
```shell
mkdir build && cd build && cmake -G "Unix Makefiles" .. && cmake --build .
```
Ensure that you avoid exposing godot-cpp symbols - this might lead to hard to debug errors if you ever load multiple
plugins using difference godot-cpp versions. Use visibility hidden whenever possible:
```cmake
set_target_properties(<all-my-plugin-related-targets> PROPERTIES CXX_VISIBILITY_PRESET hidden)
```
## Todo
Test build for Windows, Mac and mingw.

View File

@@ -1,353 +0,0 @@
CMake
=====
.. warning::
The CMake scripts do not have feature parity with the SCons ones at this
stage and are still a work in progress. There are a number of people who
have been working on alternative CMake solutions that are frequently
referenced in the discord chats: Ivan's cmake-rewrite_ branch and
Vorlac's godot-roguelite_ Project
.. _cmake-rewrite: https://github.com/IvanInventor/godot-cpp/tree/cmake-rewrite
.. _godot-roguelite: https://github.com/vorlac/godot-roguelite
Introduction
------------
Compiling godot-cpp independently of an extension project is mainly for
godot-cpp developers, package maintainers, and CI/CD. Look to the
godot-cpp-template_ for a practical example on how to consume the godot-cpp
library as part of a Godot extension.
Configuration examples are listed at the bottom of the page.
.. _godot-cpp-template: https://github.com/godotengine/godot-cpp-template
Debug vs template_debug
-----------------------
Something I've seen come up many times is the conflation of a compilation of c++
source code with debug symbols enabled, and compiling a Godot extension with
debug features enabled. The two concepts are not mutually inclusive.
- debug_features
Enables a pre-processor definition to selectively compile code to help
users of a Godot extension with their own project.
debug features are enabled in editor and template_debug builds, which can be specified during the configure phase like so
``cmake -S . -B cmake-build -DGODOTCPP_TARGET=<target choice>``
- Debug
Sets compiler flags so that debug symbols are generated to help godot
extension developers debug their extension.
``Debug`` is the default build type for CMake projects, to select another it depends on the generator used
For single configuration generators, add to the configure command:
``-DCMAKE_BUILD_TYPE=<type>``
For multi-config generators add to the build command:
``--config <type>``
where ``<type>`` is one of ``Debug``, ``Release``, ``RelWithDebInfo``, ``MinSizeRel``
SCons Deviations
----------------
Not everything from SCons can be perfectly representable in CMake, here are
the notable differences.
- debug_symbols
No longer has an explicit option, and is enabled via Debug-like CMake
build configurations; ``Debug``, ``RelWithDebInfo``.
- dev_build
Does not define ``NDEBUG`` when disabled, ``NDEBUG`` is set via Release-like
CMake build configurations; ``Release``, ``MinSizeRel``.
- arch
CMake sets the architecture via the toolchain files, macos universal is controlled vua the ``CMAKE_OSX_ARCHITECTURES``
property which is copied to targets when they are defined.
- debug_crt
CMake controls linking to windows runtime libraries by copying the value of ``CMAKE_MSVC_RUNTIME_LIBRARIES`` to targets as they are defined.
godot-cpp will set this variable if it isn't already set. so include it before other dependencies to have the value propagate across the projects.
Testing Integration
-------------------
The testing target ``godot-cpp-test`` is guarded by ``GODOTCPP_ENABLE_TESTING`` which is off by default.
To configure and build the godot-cpp project to enable the integration
testing targets the command will look something like:
.. code-block::
# Assuming our current directory is the godot-cpp source root
cmake -S . -B cmake-build -DGODOTCPP_ENABLE_TESTING=YES
cmake --build cmake-build --target godot-cpp-test
Basic walkthrough
-----------------
.. topic:: Clone the git repository
.. code-block::
git clone https://github.com/godotengine/godot-cpp.git
Cloning into 'godot-cpp'...
...
cd godot-cpp
.. topic:: Options
To list the available options CMake use the ``-L[AH]`` option. ``A`` is for
advanced, and ``H`` is for help strings.
.. code-block::
cmake .. -LH
Options are specified on the command line when configuring eg.
.. code-block::
cmake .. -DGODOTCPP_USE_HOT_RELOAD:BOOL=ON \
-DGODOTCPP_PRECISION:STRING=double \
-DCMAKE_BUILD_TYPE:STRING=Debug
Review setting-build-variables_ and build-configurations_ for more information.
.. _setting-build-variables: https://cmake.org/cmake/help/latest/guide/user-interaction/index.html#setting-build-variables
.. _build-configurations: https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#build-configurations
A non-exhaustive list of options:
.. code-block::
// Path to a custom GDExtension API JSON file (takes precedence over `GODOTCPP_GDEXTENSION_DIR`) ( /path/to/custom_api_file )
`GODOTCPP_CUSTOM_API_FILE:FILEPATH=`
// Force disabling exception handling code (ON|OFF)
GODOTCPP_DISABLE_EXCEPTIONS:BOOL=ON
// Path to a custom directory containing GDExtension interface header and API JSON file ( /path/to/gdextension_dir )
GODOTCPP_GDEXTENSION_DIR:PATH=gdextension
// Set the floating-point precision level (single|double)
GODOTCPP_PRECISION:STRING=single
// Enable the extra accounting required to support hot reload. (ON|OFF)
GODOTCPP_USE_HOT_RELOAD:BOOL=
.. topic:: Configure the build
.. code-block::
cmake -S . -B cmake-build -G Ninja
``-S .`` Specifies the source directory
``-B cmake-build`` Specifies the build directory
``-G Ninja`` Specifies the Generator
The source directory in this example is the source code for godot-cpp.
The build directory is so that generated files do not clutter up the source tree.
CMake doesn't build the code, it generates the files that another tool uses
to build the code, in this case Ninja.
To see the list of generators run ``cmake --help``.
.. topic:: Compiling
Tell cmake to invoke the build system it generated in the specified directory.
The default target is template_debug and the default build configuration is Debug.
.. code-block::
cmake --build cmake-build
Examples
--------
Windows and MSVC - Release
~~~~~~~~~~~~~~~~~~~~~~~~~~
So long as CMake is installed from the `CMake Downloads`_ page and in the PATH,
and Microsoft Visual Studio is installed with c++ support, CMake will detect
the MSVC compiler.
Note that Visual Studio is a Multi-Config Generator so the build configuration
needs to be specified at build time ie ``--config Release``
.. _CMake downloads: https://cmake.org/download/
.. code-block::
# Assuming our current directory is the godot-cpp source root
cmake -S . -B cmake-build -DGODOTCPP_ENABLE_TESTING=YES
cmake --build cmake-build -t godot-cpp-test --config Release
MSys2/clang64, "Ninja" - Debug
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Assumes the ming-w64-clang-x86_64-toolchain is installed
Note that Ninja is a Single-Config Generator so the build type
needs to be specified at Configure time.
Using the msys2/clang64 shell
.. code-block::
# Assuming our current directory is the godot-cpp source root
cmake -S . -B cmake-build -G"Ninja" -DGODOTCPP_ENABLE_TESTING=YES -DCMAKE_BUILD_TYPE=Release
cmake --build cmake-build -t godot-cpp-test
MSys2/clang64, "Ninja Multi-Config" - dev_build, Debug Symbols
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Assumes the ming-w64-clang-x86_64-toolchain is installed
This time we are choosing the 'Ninja Multi-Config' generator, so the build
type is specified at build time.
Using the msys2/clang64 shell
.. code-block::
# Assuming our current directory is the godot-cpp source root
cmake -S . -B cmake-build -G"Ninja Multi-Config" -DGODOTCPP_ENABLE_TESTING=YES -DGODOTCPP_DEV_BUILD:BOOL=ON
cmake --build cmake-build -t godot-cpp-test --config Debug
Emscripten for web platform
~~~~~~~~~~~~~~~~~~~~~~~~~~~
I've only tested this on windows so far.
I cloned and installed the latest Emscripten tools to ``c:\emsdk``
At the time of writing that was v3.1.69
I've been using ``C:\emsdk\emsdk.ps1 activate latest`` to enable the
environment from powershell in the current shell.
The ``emcmake.bat`` utility adds the emscripten toolchain to the CMake command
It can also be added manually, the location is listed inside the emcmake.bat file
.. code-block::
# Assuming our current directory is the godot-cpp source root
C:\emsdk\emsdk.ps1 activate latest
emcmake.bat cmake -S . -B cmake-build-web -DCMAKE_BUILD_TYPE=Release
cmake --build cmake-build-web
Android Cross Compile from Windows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There are two separate paths you can choose when configuring for android.
Use the ``CMAKE_ANDROID_*`` variables specified on the commandline or in your
own toolchain file as listed in the cmake-toolchains_ documentation
.. _cmake-toolchains: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android-with-the-ndk
Or use the toolchain and scripts provided by the Android SDK and make changes
using the ``ANDROID_*`` variables listed there. Where ``<version>`` is whatever
ndk version you have installed (tested with `28.1.13356709`) and ``<platform>``
is for android sdk platform, (tested with ``android-29``)
.. warning::
The Android SDK website explicitly states that they do not support using
the CMake built-in method, and recommends you stick with their toolchain
files.
.. topic:: Using your own toolchain file as described in the CMake documentation
.. code-block::
# Assuming our current directory is the godot-cpp source root
cmake -S . -B cmake-build --toolchain my_toolchain.cmake
cmake --build cmake-build -t template_release
Doing the equivalent on just using the command line
.. code-block::
# Assuming our current directory is the godot-cpp source root
cmake -S . -B cmake-build \
-DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION=<platform> \
-DCMAKE_ANDROID_ARCH_ABI=<arch> \
-DCMAKE_ANDROID_NDK=/path/to/android-ndk
cmake --build cmake-build
.. topic:: Using the toolchain file from the Android SDK
Defaults to minimum supported version( android-16 in my case) and armv7-a.
.. code-block::
# Assuming our current directory is the godot-cpp source root
cmake -S . -B cmake-build --toolchain $ANDROID_HOME/ndk/<version>/build/cmake/android.toolchain.cmake
cmake --build cmake-build
Specify Android platform and ABI
.. code-block::
# Assuming our current directory is the godot-cpp source root
cmake -S . -B cmake-build --toolchain $ANDROID_HOME/ndk/<version>/build/cmake/android.toolchain.cmake \
-DANDROID_PLATFORM:STRING=android-29 \
-DANDROID_ABI:STRING=armeabi-v7a
cmake --build cmake-build
Toolchains
----------
This section attempts to list the host and target combinations that have been
at tested.
Linux Host
~~~~~~~~~~
Macos Host
~~~~~~~~~~
:System: Mac Mini
:OS Name: Sequoia 15.0.1
:Processor: Apple M2
* AppleClang
Windows Host
~~~~~~~~~~~~
:OS Name: Windows 11
:Processor: AMD Ryzen 7 6800HS Creator Edition
* `Microsoft Visual Studio 17 2022 <https://visualstudio.microsoft.com/vs/>`_
* `LLVM <https://llvm.org/>`_
* `LLVM-MinGW <https://github.com/mstorsjo/llvm-mingw/releases>`_
* aarch64-w64-mingw32
* armv7-w64-mingw32
* i686-w64-mingw32
* x86_64-w64-mingw32
* `AndroidSDK <https://developer.android.com/studio/#command-tools>`_
* `Emscripten <https://emscripten.org/>`_
* `MinGW-W64-builds <https://github.com/niXman/mingw-builds-binaries/releases>`_
* `Jetbrains-CLion <https://www.jetbrains.com/clion/>`_
Jetbrains builtin compiler is just the MingW64 above.
* `MSYS2 <https://www.msys2.org/>`_
Necessary reading about MSYS2 `environments <https://www.msys2.org/docs/environments/>`_
* ucrt64
* clang64
* mingw32
* mingw64
* clangarm64

View File

@@ -1,55 +0,0 @@
#!/usr/bin/env python
import glob
import os
import zlib
def generate_doc_source(dst, source):
g = open(dst, "w", encoding="utf-8")
buf = ""
docbegin = ""
docend = ""
for src in source:
src_path = str(src)
if not src_path.endswith(".xml"):
continue
with open(src_path, "r", encoding="utf-8") as f:
content = f.read()
buf += content
buf = (docbegin + buf + docend).encode("utf-8")
decomp_size = len(buf)
# Use maximum zlib compression level to further reduce file size
# (at the cost of initial build times).
buf = zlib.compress(buf, zlib.Z_BEST_COMPRESSION)
g.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
g.write("\n")
g.write("#include <godot_cpp/godot.hpp>\n")
g.write("\n")
g.write('static const char *_doc_data_hash = "' + str(hash(buf)) + '";\n')
g.write("static const int _doc_data_uncompressed_size = " + str(decomp_size) + ";\n")
g.write("static const int _doc_data_compressed_size = " + str(len(buf)) + ";\n")
g.write("static const unsigned char _doc_data_compressed[] = {\n")
for i in range(len(buf)):
g.write("\t" + str(buf[i]) + ",\n")
g.write("};\n")
g.write("\n")
g.write(
"static godot::internal::DocDataRegistration _doc_data_registration(_doc_data_hash, _doc_data_uncompressed_size, _doc_data_compressed_size, _doc_data_compressed);\n"
)
g.write("\n")
g.close()
def scons_generate_doc_source(target, source, env):
generate_doc_source(str(target[0]), source)
def generate_doc_source_from_directory(target, directory):
generate_doc_source(target, glob.glob(os.path.join(directory, "*.xml")))

File diff suppressed because it is too large Load Diff

View File

@@ -28,22 +28,22 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GDEXTENSION_INTERFACE_H
#define GDEXTENSION_INTERFACE_H
/* This is a C class header, you can copy it and use it directly in your own binders.
* Together with the JSON file, you should be able to generate any binder.
*/
#ifndef __cplusplus
#include <stddef.h>
#include <stdint.h>
#ifndef __cplusplus
typedef uint32_t char32_t;
typedef uint16_t char16_t;
#else
#include <cstddef>
#include <cstdint>
#endif
#ifdef __cplusplus
extern "C" {
#endif
@@ -198,7 +198,6 @@ typedef struct {
typedef void (*GDExtensionVariantFromTypeConstructorFunc)(GDExtensionUninitializedVariantPtr, GDExtensionTypePtr);
typedef void (*GDExtensionTypeFromVariantConstructorFunc)(GDExtensionUninitializedTypePtr, GDExtensionVariantPtr);
typedef void *(*GDExtensionVariantGetInternalPtrFunc)(GDExtensionVariantPtr);
typedef void (*GDExtensionPtrOperatorEvaluator)(GDExtensionConstTypePtr p_left, GDExtensionConstTypePtr p_right, GDExtensionTypePtr r_result);
typedef void (*GDExtensionPtrBuiltInMethod)(GDExtensionTypePtr p_base, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return, int p_argument_count);
typedef void (*GDExtensionPtrConstructor)(GDExtensionUninitializedTypePtr p_base, const GDExtensionConstTypePtr *p_args);
@@ -269,13 +268,10 @@ typedef void (*GDExtensionClassReference)(GDExtensionClassInstancePtr p_instance
typedef void (*GDExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
typedef void (*GDExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance)(void *p_class_userdata);
typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance2)(void *p_class_userdata, GDExtensionBool p_notify_postinitialize);
typedef void (*GDExtensionClassFreeInstance)(void *p_class_userdata, GDExtensionClassInstancePtr p_instance);
typedef GDExtensionClassInstancePtr (*GDExtensionClassRecreateInstance)(void *p_class_userdata, GDExtensionObjectPtr p_object);
typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual)(void *p_class_userdata, GDExtensionConstStringNamePtr p_name);
typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual2)(void *p_class_userdata, GDExtensionConstStringNamePtr p_name, uint32_t p_hash);
typedef void *(*GDExtensionClassGetVirtualCallData)(void *p_class_userdata, GDExtensionConstStringNamePtr p_name);
typedef void *(*GDExtensionClassGetVirtualCallData2)(void *p_class_userdata, GDExtensionConstStringNamePtr p_name, uint32_t p_hash);
typedef void (*GDExtensionClassCallVirtualWithData)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, void *p_virtual_call_userdata, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
typedef struct {
@@ -296,7 +292,7 @@ typedef struct {
GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function.
GDExtensionClassGetRID get_rid_func;
void *class_userdata; // Per-class user data, later accessible in instance bindings.
} GDExtensionClassCreationInfo; // Deprecated. Use GDExtensionClassCreationInfo4 instead.
} GDExtensionClassCreationInfo; // Deprecated. Use GDExtensionClassCreationInfo3 instead.
typedef struct {
GDExtensionBool is_virtual;
@@ -329,7 +325,7 @@ typedef struct {
GDExtensionClassCallVirtualWithData call_virtual_with_data_func;
GDExtensionClassGetRID get_rid_func;
void *class_userdata; // Per-class user data, later accessible in instance bindings.
} GDExtensionClassCreationInfo2; // Deprecated. Use GDExtensionClassCreationInfo4 instead.
} GDExtensionClassCreationInfo2; // Deprecated. Use GDExtensionClassCreationInfo3 instead.
typedef struct {
GDExtensionBool is_virtual;
@@ -363,49 +359,10 @@ typedef struct {
GDExtensionClassCallVirtualWithData call_virtual_with_data_func;
GDExtensionClassGetRID get_rid_func;
void *class_userdata; // Per-class user data, later accessible in instance bindings.
} GDExtensionClassCreationInfo3; // Deprecated. Use GDExtensionClassCreationInfo4 instead.
typedef struct {
GDExtensionBool is_virtual;
GDExtensionBool is_abstract;
GDExtensionBool is_exposed;
GDExtensionBool is_runtime;
GDExtensionConstStringPtr icon_path;
GDExtensionClassSet set_func;
GDExtensionClassGet get_func;
GDExtensionClassGetPropertyList get_property_list_func;
GDExtensionClassFreePropertyList2 free_property_list_func;
GDExtensionClassPropertyCanRevert property_can_revert_func;
GDExtensionClassPropertyGetRevert property_get_revert_func;
GDExtensionClassValidateProperty validate_property_func;
GDExtensionClassNotification2 notification_func;
GDExtensionClassToString to_string_func;
GDExtensionClassReference reference_func;
GDExtensionClassUnreference unreference_func;
GDExtensionClassCreateInstance2 create_instance_func; // (Default) constructor; mandatory. If the class is not instantiable, consider making it virtual or abstract.
GDExtensionClassFreeInstance free_instance_func; // Destructor; mandatory.
GDExtensionClassRecreateInstance recreate_instance_func;
// Queries a virtual function by name and returns a callback to invoke the requested virtual function.
GDExtensionClassGetVirtual2 get_virtual_func;
// Paired with `call_virtual_with_data_func`, this is an alternative to `get_virtual_func` for extensions that
// need or benefit from extra data when calling virtual functions.
// Returns user data that will be passed to `call_virtual_with_data_func`.
// Returning `NULL` from this function signals to Godot that the virtual function is not overridden.
// Data returned from this function should be managed by the extension and must be valid until the extension is deinitialized.
// You should supply either `get_virtual_func`, or `get_virtual_call_data_func` with `call_virtual_with_data_func`.
GDExtensionClassGetVirtualCallData2 get_virtual_call_data_func;
// Used to call virtual functions when `get_virtual_call_data_func` is not null.
GDExtensionClassCallVirtualWithData call_virtual_with_data_func;
void *class_userdata; // Per-class user data, later accessible in instance bindings.
} GDExtensionClassCreationInfo4;
typedef GDExtensionClassCreationInfo4 GDExtensionClassCreationInfo5;
} GDExtensionClassCreationInfo3;
typedef void *GDExtensionClassLibraryPtr;
/* Passed a pointer to a PackedStringArray that should be filled with the classes that may be used by the GDExtension. */
typedef void (*GDExtensionEditorGetClassesUsedCallback)(GDExtensionTypePtr p_packed_string_array);
/* Method */
typedef enum {
@@ -429,9 +386,7 @@ typedef enum {
GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT32,
GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64,
GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT,
GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE,
GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_CHAR16,
GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_CHAR32,
GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE
} GDExtensionClassMethodArgumentMetadata;
typedef void (*GDExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
@@ -726,9 +681,6 @@ typedef struct {
} GDExtensionScriptInstanceInfo3;
typedef void (*GDExtensionWorkerThreadPoolGroupTask)(void *, uint32_t);
typedef void (*GDExtensionWorkerThreadPoolTask)(void *);
/* INITIALIZATION */
typedef enum {
@@ -739,9 +691,6 @@ typedef enum {
GDEXTENSION_MAX_INITIALIZATION_LEVEL,
} GDExtensionInitializationLevel;
typedef void (*GDExtensionInitializeCallback)(void *p_userdata, GDExtensionInitializationLevel p_level);
typedef void (*GDExtensionDeinitializeCallback)(void *p_userdata, GDExtensionInitializationLevel p_level);
typedef struct {
/* Minimum initialization level required.
* If Core or Servers, the extension needs editor or game restart to take effect */
@@ -749,8 +698,8 @@ typedef struct {
/* Up to the user to supply when initializing */
void *userdata;
/* This function will be called multiple times for each initialization level. */
GDExtensionInitializeCallback initialize;
GDExtensionDeinitializeCallback deinitialize;
void (*initialize)(void *userdata, GDExtensionInitializationLevel p_level);
void (*deinitialize)(void *userdata, GDExtensionInitializationLevel p_level);
} GDExtensionInitialization;
typedef void (*GDExtensionInterfaceFunctionPtr)();
@@ -801,41 +750,9 @@ typedef struct {
const char *string;
} GDExtensionGodotVersion;
typedef struct {
uint32_t major;
uint32_t minor;
uint32_t patch;
uint32_t hex; // Full version encoded as hexadecimal with one byte (2 hex digits) per number (e.g. for "3.1.12" it would be 0x03010C)
const char *status; // (e.g. "stable", "beta", "rc1", "rc2")
const char *build; // (e.g. "custom_build")
const char *hash; // Full Git commit hash.
uint64_t timestamp; // Git commit date UNIX timestamp in seconds, or 0 if unavailable.
const char *string; // (e.g. "Godot v3.1.4.stable.official.mono")
} GDExtensionGodotVersion2;
/* Called when starting the main loop. */
typedef void (*GDExtensionMainLoopStartupCallback)();
/* Called when shutting down the main loop. */
typedef void (*GDExtensionMainLoopShutdownCallback)();
/* Called for every frame iteration of the main loop. */
typedef void (*GDExtensionMainLoopFrameCallback)();
typedef struct {
// Will be called after Godot is started and is fully initialized.
GDExtensionMainLoopStartupCallback startup_func;
// Will be called before Godot is shutdown when it is still fully initialized.
GDExtensionMainLoopShutdownCallback shutdown_func;
// Will be called for each process frame. This will run after all `_process()` methods on Node, and before `ScriptServer::frame()`.
// This is intended to be the equivalent of `ScriptLanguage::frame()` for GDExtension language bindings that don't use the script API.
GDExtensionMainLoopFrameCallback frame_func;
} GDExtensionMainLoopCallbacks;
/**
* @name get_godot_version
* @since 4.1
* @deprecated in Godot 4.5. Use `get_godot_version2` instead.
*
* Gets the Godot version that the GDExtension was loaded into.
*
@@ -843,16 +760,6 @@ typedef struct {
*/
typedef void (*GDExtensionInterfaceGetGodotVersion)(GDExtensionGodotVersion *r_godot_version);
/**
* @name get_godot_version2
* @since 4.5
*
* Gets the Godot version that the GDExtension was loaded into.
*
* @param r_godot_version A pointer to the structure to write the version information into.
*/
typedef void (*GDExtensionInterfaceGetGodotVersion2)(GDExtensionGodotVersion2 *r_godot_version);
/* INTERFACE: Memory */
/**
@@ -898,7 +805,7 @@ typedef void (*GDExtensionInterfaceMemFree)(void *p_ptr);
*
* Logs an error to Godot's built-in debugger and to the OS terminal.
*
* @param p_description The code triggering the error.
* @param p_description The code trigging the error.
* @param p_function The function name where the error occurred.
* @param p_file The file where the error occurred.
* @param p_line The line where the error occurred.
@@ -912,7 +819,7 @@ typedef void (*GDExtensionInterfacePrintError)(const char *p_description, const
*
* Logs an error with a message to Godot's built-in debugger and to the OS terminal.
*
* @param p_description The code triggering the error.
* @param p_description The code trigging the error.
* @param p_message The message to show along with the error.
* @param p_function The function name where the error occurred.
* @param p_file The file where the error occurred.
@@ -927,7 +834,7 @@ typedef void (*GDExtensionInterfacePrintErrorWithMessage)(const char *p_descript
*
* Logs a warning to Godot's built-in debugger and to the OS terminal.
*
* @param p_description The code triggering the warning.
* @param p_description The code trigging the warning.
* @param p_function The function name where the warning occurred.
* @param p_file The file where the warning occurred.
* @param p_line The line where the warning occurred.
@@ -941,7 +848,7 @@ typedef void (*GDExtensionInterfacePrintWarning)(const char *p_description, cons
*
* Logs a warning with a message to Godot's built-in debugger and to the OS terminal.
*
* @param p_description The code triggering the warning.
* @param p_description The code trigging the warning.
* @param p_message The message to show along with the warning.
* @param p_function The function name where the warning occurred.
* @param p_file The file where the warning occurred.
@@ -956,7 +863,7 @@ typedef void (*GDExtensionInterfacePrintWarningWithMessage)(const char *p_descri
*
* Logs a script error to Godot's built-in debugger and to the OS terminal.
*
* @param p_description The code triggering the error.
* @param p_description The code trigging the error.
* @param p_function The function name where the error occurred.
* @param p_file The file where the error occurred.
* @param p_line The line where the error occurred.
@@ -970,7 +877,7 @@ typedef void (*GDExtensionInterfacePrintScriptError)(const char *p_description,
*
* Logs a script error with a message to Godot's built-in debugger and to the OS terminal.
*
* @param p_description The code triggering the error.
* @param p_description The code trigging the error.
* @param p_message The message to show along with the error.
* @param p_function The function name where the error occurred.
* @param p_file The file where the error occurred.
@@ -1047,7 +954,7 @@ typedef void (*GDExtensionInterfaceVariantCall)(GDExtensionVariantPtr p_self, GD
*
* Calls a static method on a Variant.
*
* @param p_type The variant type.
* @param p_self A pointer to the Variant.
* @param p_method A pointer to a StringName identifying the method.
* @param p_args A pointer to a C array of Variant.
* @param p_argument_count The number of arguments.
@@ -1333,7 +1240,7 @@ typedef GDExtensionVariantType (*GDExtensionInterfaceVariantGetType)(GDExtension
* @param p_self A pointer to the Variant.
* @param p_method A pointer to a StringName with the method name.
*
* @return true if the variant has the given method; otherwise false.
* @return
*/
typedef GDExtensionBool (*GDExtensionInterfaceVariantHasMethod)(GDExtensionConstVariantPtr p_self, GDExtensionConstStringNamePtr p_method);
@@ -1346,7 +1253,7 @@ typedef GDExtensionBool (*GDExtensionInterfaceVariantHasMethod)(GDExtensionConst
* @param p_type The Variant type.
* @param p_member A pointer to a StringName with the member name.
*
* @return true if the variant has the given method; otherwise false.
* @return
*/
typedef GDExtensionBool (*GDExtensionInterfaceVariantHasMember)(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_member);
@@ -1364,21 +1271,6 @@ typedef GDExtensionBool (*GDExtensionInterfaceVariantHasMember)(GDExtensionVaria
*/
typedef GDExtensionBool (*GDExtensionInterfaceVariantHasKey)(GDExtensionConstVariantPtr p_self, GDExtensionConstVariantPtr p_key, GDExtensionBool *r_valid);
/**
* @name variant_get_object_instance_id
* @since 4.4
*
* Gets the object instance ID from a variant of type GDEXTENSION_VARIANT_TYPE_OBJECT.
*
* If the variant isn't of type GDEXTENSION_VARIANT_TYPE_OBJECT, then zero will be returned.
* The instance ID will be returned even if the object is no longer valid - use `object_get_instance_by_id()` to check if the object is still valid.
*
* @param p_self A pointer to the Variant.
*
* @return The instance ID for the contained object.
*/
typedef GDObjectInstanceID (*GDExtensionInterfaceVariantGetObjectInstanceId)(GDExtensionConstVariantPtr p_self);
/**
* @name variant_get_type_name
* @since 4.1
@@ -1440,23 +1332,6 @@ typedef GDExtensionVariantFromTypeConstructorFunc (*GDExtensionInterfaceGetVaria
*/
typedef GDExtensionTypeFromVariantConstructorFunc (*GDExtensionInterfaceGetVariantToTypeConstructor)(GDExtensionVariantType p_type);
/**
* @name variant_get_ptr_internal_getter
* @since 4.4
*
* Provides a function pointer for retrieving a pointer to a variant's internal value.
* Access to a variant's internal value can be used to modify it in-place, or to retrieve its value without the overhead of variant conversion functions.
* It is recommended to cache the getter for all variant types in a function table to avoid retrieval overhead upon use.
*
* @note Each function assumes the variant's type has already been determined and matches the function.
* Invoking the function with a variant of a mismatched type has undefined behavior, and may lead to a segmentation fault.
*
* @param p_type The Variant type.
*
* @return A pointer to a type-specific function that returns a pointer to the internal value of a variant. Check the implementation of this function (gdextension_variant_get_ptr_internal_getter) for pointee type info of each variant type.
*/
typedef GDExtensionVariantGetInternalPtrFunc (*GDExtensionInterfaceGetVariantGetInternalPtrFunc)(GDExtensionVariantType p_type);
/**
* @name variant_get_ptr_operator_evaluator
* @since 4.1
@@ -1517,7 +1392,7 @@ typedef GDExtensionPtrDestructor (*GDExtensionInterfaceVariantGetPtrDestructor)(
* Constructs a Variant of the given type, using the first constructor that matches the given arguments.
*
* @param p_type The Variant type.
* @param r_base A pointer to a Variant to store the constructed value.
* @param p_base A pointer to a Variant to store the constructed value.
* @param p_args A pointer to a C array of Variant pointers representing the arguments for the constructor.
* @param p_argument_count The number of arguments to pass to the constructor.
* @param r_error A pointer the structure which will be updated with error information.
@@ -1740,7 +1615,7 @@ typedef GDExtensionInt (*GDExtensionInterfaceStringNewWithUtf8CharsAndLen2)(GDEx
*
* @param r_dest A pointer to a Variant to hold the newly created String.
* @param p_contents A pointer to a UTF-16 encoded C string.
* @param p_char_count The number of characters (not bytes).
* @param p_size The number of characters (not bytes).
*/
typedef void (*GDExtensionInterfaceStringNewWithUtf16CharsAndLen)(GDExtensionUninitializedStringPtr r_dest, const char16_t *p_contents, GDExtensionInt p_char_count);
@@ -1752,7 +1627,7 @@ typedef void (*GDExtensionInterfaceStringNewWithUtf16CharsAndLen)(GDExtensionUni
*
* @param r_dest A pointer to a Variant to hold the newly created String.
* @param p_contents A pointer to a UTF-16 encoded C string.
* @param p_char_count The number of characters (not bytes).
* @param p_size The number of characters (not bytes).
* @param p_default_little_endian If true, UTF-16 use little endian.
*
* @return Error code signifying if the operation successful.
@@ -1767,7 +1642,7 @@ typedef GDExtensionInt (*GDExtensionInterfaceStringNewWithUtf16CharsAndLen2)(GDE
*
* @param r_dest A pointer to a Variant to hold the newly created String.
* @param p_contents A pointer to a UTF-32 encoded C string.
* @param p_char_count The number of characters (not bytes).
* @param p_size The number of characters (not bytes).
*/
typedef void (*GDExtensionInterfaceStringNewWithUtf32CharsAndLen)(GDExtensionUninitializedStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_char_count);
@@ -1779,7 +1654,7 @@ typedef void (*GDExtensionInterfaceStringNewWithUtf32CharsAndLen)(GDExtensionUni
*
* @param r_dest A pointer to a Variant to hold the newly created String.
* @param p_contents A pointer to a wide C string.
* @param p_char_count The number of characters (not bytes).
* @param p_size The number of characters (not bytes).
*/
typedef void (*GDExtensionInterfaceStringNewWithWideCharsAndLen)(GDExtensionUninitializedStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_char_count);
@@ -2096,7 +1971,6 @@ typedef const uint8_t *(*GDExtensionInterfaceImagePtr)(GDExtensionObjectPtr p_in
* @param p_instance A pointer to a WorkerThreadPool object.
* @param p_func A pointer to a function to run in the thread pool.
* @param p_userdata A pointer to arbitrary data which will be passed to p_func.
* @param p_elements The number of element needed in the group.
* @param p_tasks The number of tasks needed in the group.
* @param p_high_priority Whether or not this is a high priority task.
* @param p_description A pointer to a String with the task description.
@@ -2105,7 +1979,7 @@ typedef const uint8_t *(*GDExtensionInterfaceImagePtr)(GDExtensionObjectPtr p_in
*
* @see WorkerThreadPool::add_group_task()
*/
typedef int64_t (*GDExtensionInterfaceWorkerThreadPoolAddNativeGroupTask)(GDExtensionObjectPtr p_instance, GDExtensionWorkerThreadPoolGroupTask p_func, void *p_userdata, int p_elements, int p_tasks, GDExtensionBool p_high_priority, GDExtensionConstStringPtr p_description);
typedef int64_t (*GDExtensionInterfaceWorkerThreadPoolAddNativeGroupTask)(GDExtensionObjectPtr p_instance, void (*p_func)(void *, uint32_t), void *p_userdata, int p_elements, int p_tasks, GDExtensionBool p_high_priority, GDExtensionConstStringPtr p_description);
/**
* @name worker_thread_pool_add_native_task
@@ -2121,7 +1995,7 @@ typedef int64_t (*GDExtensionInterfaceWorkerThreadPoolAddNativeGroupTask)(GDExte
*
* @return The task ID.
*/
typedef int64_t (*GDExtensionInterfaceWorkerThreadPoolAddNativeTask)(GDExtensionObjectPtr p_instance, GDExtensionWorkerThreadPoolTask p_func, void *p_userdata, GDExtensionBool p_high_priority, GDExtensionConstStringPtr p_description);
typedef int64_t (*GDExtensionInterfaceWorkerThreadPoolAddNativeTask)(GDExtensionObjectPtr p_instance, void (*p_func)(void *), void *p_userdata, GDExtensionBool p_high_priority, GDExtensionConstStringPtr p_description);
/* INTERFACE: Packed Array */
@@ -2414,7 +2288,6 @@ typedef GDExtensionVariantPtr (*GDExtensionInterfaceArrayOperatorIndexConst)(GDE
/**
* @name array_ref
* @since 4.1
* @deprecated in Godot 4.5. use `Array::operator=` instead.
*
* Sets an Array to be a reference to another Array object.
*
@@ -2464,22 +2337,6 @@ typedef GDExtensionVariantPtr (*GDExtensionInterfaceDictionaryOperatorIndex)(GDE
*/
typedef GDExtensionVariantPtr (*GDExtensionInterfaceDictionaryOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionConstVariantPtr p_key);
/**
* @name dictionary_set_typed
* @since 4.4
*
* Makes a Dictionary into a typed Dictionary.
*
* @param p_self A pointer to the Dictionary.
* @param p_key_type The type of Variant the Dictionary key will store.
* @param p_key_class_name A pointer to a StringName with the name of the object (if p_key_type is GDEXTENSION_VARIANT_TYPE_OBJECT).
* @param p_key_script A pointer to a Script object (if p_key_type is GDEXTENSION_VARIANT_TYPE_OBJECT and the base class is extended by a script).
* @param p_value_type The type of Variant the Dictionary value will store.
* @param p_value_class_name A pointer to a StringName with the name of the object (if p_value_type is GDEXTENSION_VARIANT_TYPE_OBJECT).
* @param p_value_script A pointer to a Script object (if p_value_type is GDEXTENSION_VARIANT_TYPE_OBJECT and the base class is extended by a script).
*/
typedef void (*GDExtensionInterfaceDictionarySetTyped)(GDExtensionTypePtr p_self, GDExtensionVariantType p_key_type, GDExtensionConstStringNamePtr p_key_class_name, GDExtensionConstVariantPtr p_key_script, GDExtensionVariantType p_value_type, GDExtensionConstStringNamePtr p_value_class_name, GDExtensionConstVariantPtr p_value_script);
/* INTERFACE: Object */
/**
@@ -2539,10 +2396,10 @@ typedef GDExtensionObjectPtr (*GDExtensionInterfaceGlobalGetSingleton)(GDExtensi
* Gets a pointer representing an Object's instance binding.
*
* @param p_o A pointer to the Object.
* @param p_token A token the library received by the GDExtension's entry point function.
* @param p_library A token the library received by the GDExtension's entry point function.
* @param p_callbacks A pointer to a GDExtensionInstanceBindingCallbacks struct.
*
* @return A pointer to the instance binding.
* @return
*/
typedef void *(*GDExtensionInterfaceObjectGetInstanceBinding)(GDExtensionObjectPtr p_o, void *p_token, const GDExtensionInstanceBindingCallbacks *p_callbacks);
@@ -2553,7 +2410,7 @@ typedef void *(*GDExtensionInterfaceObjectGetInstanceBinding)(GDExtensionObjectP
* Sets an Object's instance binding.
*
* @param p_o A pointer to the Object.
* @param p_token A token the library received by the GDExtension's entry point function.
* @param p_library A token the library received by the GDExtension's entry point function.
* @param p_binding A pointer to the instance binding.
* @param p_callbacks A pointer to a GDExtensionInstanceBindingCallbacks struct.
*/
@@ -2566,7 +2423,7 @@ typedef void (*GDExtensionInterfaceObjectSetInstanceBinding)(GDExtensionObjectPt
* Free an Object's instance binding.
*
* @param p_o A pointer to the Object.
* @param p_token A token the library received by the GDExtension's entry point function.
* @param p_library A token the library received by the GDExtension's entry point function.
*/
typedef void (*GDExtensionInterfaceObjectFreeInstanceBinding)(GDExtensionObjectPtr p_o, void *p_token);
@@ -2576,13 +2433,11 @@ typedef void (*GDExtensionInterfaceObjectFreeInstanceBinding)(GDExtensionObjectP
*
* Sets an extension class instance on a Object.
*
* `p_classname` should be a registered extension class and should extend the `p_o` Object's class.
*
* @param p_o A pointer to the Object.
* @param p_classname A pointer to a StringName with the registered extension class's name.
* @param p_instance A pointer to the extension class instance.
*/
typedef void (*GDExtensionInterfaceObjectSetInstance)(GDExtensionObjectPtr p_o, GDExtensionConstStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance);
typedef void (*GDExtensionInterfaceObjectSetInstance)(GDExtensionObjectPtr p_o, GDExtensionConstStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */
/**
* @name object_get_class_name
@@ -2647,7 +2502,7 @@ typedef GDObjectInstanceID (*GDExtensionInterfaceObjectGetInstanceId)(GDExtensio
* @param p_object A pointer to the Object.
* @param p_method A pointer to a StringName identifying the method.
*
* @return true if the object has a script and that script has a method with the given name. Returns false if the object has no script.
* @returns true if the object has a script and that script has a method with the given name. Returns false if the object has no script.
*/
typedef GDExtensionBool (*GDExtensionInterfaceObjectHasScriptMethod)(GDExtensionConstObjectPtr p_object, GDExtensionConstStringNamePtr p_method);
@@ -2778,17 +2633,6 @@ typedef void (*GDExtensionInterfacePlaceHolderScriptInstanceUpdate)(GDExtensionS
*/
typedef GDExtensionScriptInstanceDataPtr (*GDExtensionInterfaceObjectGetScriptInstance)(GDExtensionConstObjectPtr p_object, GDExtensionObjectPtr p_language);
/**
* @name object_set_script_instance
* @since 4.5
*
* Set the script instance data attached to this object.
*
* @param p_object A pointer to the Object.
* @param p_script_instance A pointer to the script instance data to attach to this object.
*/
typedef void (*GDExtensionInterfaceObjectSetScriptInstance)(GDExtensionObjectPtr p_object, GDExtensionScriptInstanceDataPtr p_script_instance);
/* INTERFACE: Callable */
/**
@@ -2828,8 +2672,6 @@ typedef void (*GDExtensionInterfaceCallableCustomCreate2)(GDExtensionUninitializ
*
* @param p_callable A pointer to a Callable.
* @param p_token A pointer to an address that uniquely identifies the GDExtension.
*
* @return The userdata pointer given when creating this custom Callable.
*/
typedef void *(*GDExtensionInterfaceCallableCustomGetUserData)(GDExtensionConstTypePtr p_callable, void *p_token);
@@ -2838,7 +2680,6 @@ typedef void *(*GDExtensionInterfaceCallableCustomGetUserData)(GDExtensionConstT
/**
* @name classdb_construct_object
* @since 4.1
* @deprecated in Godot 4.4. Use `classdb_construct_object2` instead.
*
* Constructs an Object of the requested class.
*
@@ -2850,22 +2691,6 @@ typedef void *(*GDExtensionInterfaceCallableCustomGetUserData)(GDExtensionConstT
*/
typedef GDExtensionObjectPtr (*GDExtensionInterfaceClassdbConstructObject)(GDExtensionConstStringNamePtr p_classname);
/**
* @name classdb_construct_object2
* @since 4.4
*
* Constructs an Object of the requested class.
*
* The passed class must be a built-in godot class, or an already-registered extension class. In both cases, object_set_instance() should be called to fully initialize the object.
*
* "NOTIFICATION_POSTINITIALIZE" must be sent after construction.
*
* @param p_classname A pointer to a StringName with the class name.
*
* @return A pointer to the newly created Object.
*/
typedef GDExtensionObjectPtr (*GDExtensionInterfaceClassdbConstructObject2)(GDExtensionConstStringNamePtr p_classname);
/**
* @name classdb_get_method_bind
* @since 4.1
@@ -2897,7 +2722,7 @@ typedef void *(*GDExtensionInterfaceClassdbGetClassTag)(GDExtensionConstStringNa
/**
* @name classdb_register_extension_class
* @since 4.1
* @deprecated in Godot 4.2. Use `classdb_register_extension_class4` instead.
* @deprecated in Godot 4.2. Use `classdb_register_extension_class3` instead.
*
* Registers an extension class in the ClassDB.
*
@@ -2913,7 +2738,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass)(GDExtensionCla
/**
* @name classdb_register_extension_class2
* @since 4.2
* @deprecated in Godot 4.3. Use `classdb_register_extension_class4` instead.
* @deprecated in Godot 4.3. Use `classdb_register_extension_class3` instead.
*
* Registers an extension class in the ClassDB.
*
@@ -2929,7 +2754,6 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass2)(GDExtensionCl
/**
* @name classdb_register_extension_class3
* @since 4.3
* @deprecated in Godot 4.4. Use `classdb_register_extension_class4` instead.
*
* Registers an extension class in the ClassDB.
*
@@ -2938,41 +2762,10 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass2)(GDExtensionCl
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param p_class_name A pointer to a StringName with the class name.
* @param p_parent_class_name A pointer to a StringName with the parent class name.
* @param p_extension_funcs A pointer to a GDExtensionClassCreationInfo3 struct.
* @param p_extension_funcs A pointer to a GDExtensionClassCreationInfo2 struct.
*/
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass3)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs);
/**
* @name classdb_register_extension_class4
* @since 4.4
* @deprecated in Godot 4.5. Use `classdb_register_extension_class5` instead.
*
* Registers an extension class in the ClassDB.
*
* Provided struct can be safely freed once the function returns.
*
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param p_class_name A pointer to a StringName with the class name.
* @param p_parent_class_name A pointer to a StringName with the parent class name.
* @param p_extension_funcs A pointer to a GDExtensionClassCreationInfo4 struct.
*/
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass4)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs);
/**
* @name classdb_register_extension_class5
* @since 4.5
*
* Registers an extension class in the ClassDB.
*
* Provided struct can be safely freed once the function returns.
*
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param p_class_name A pointer to a StringName with the class name.
* @param p_parent_class_name A pointer to a StringName with the parent class name.
* @param p_extension_funcs A pointer to a GDExtensionClassCreationInfo5 struct.
*/
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass5)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo5 *p_extension_funcs);
/**
* @name classdb_register_extension_class_method
* @since 4.1
@@ -3101,12 +2894,10 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClassSignal)(GDExtens
*
* Unregisters an extension class in the ClassDB.
*
* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first.
*
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param p_class_name A pointer to a StringName with the class name.
*/
typedef void (*GDExtensionInterfaceClassdbUnregisterExtensionClass)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name);
typedef void (*GDExtensionInterfaceClassdbUnregisterExtensionClass)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name); /* Unregistering a parent class before a class that inherits it will result in failure. Inheritors must be unregistered first. */
/**
* @name get_library_path
@@ -3166,33 +2957,8 @@ typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars)(const char *
*/
typedef void (*GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen)(const char *p_data, GDExtensionInt p_size);
/**
* @name editor_register_get_classes_used_callback
* @since 4.5
*
* Registers a callback that Godot can call to get the list of all classes (from ClassDB) that may be used by the calling GDExtension.
*
* This is used by the editor to generate a build profile (in "Tools" > "Engine Compilation Configuration Editor..." > "Detect from project"),
* in order to recompile Godot with only the classes used.
* In the provided callback, the GDExtension should provide the list of classes that _may_ be used statically, thus the time of invocation shouldn't matter.
* If a GDExtension doesn't register a callback, Godot will assume that it could be using any classes.
*
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param p_callback The callback to retrieve the list of classes used.
*/
typedef void (*GDExtensionInterfaceEditorRegisterGetClassesUsedCallback)(GDExtensionClassLibraryPtr p_library, GDExtensionEditorGetClassesUsedCallback p_callback);
/**
* @name register_main_loop_callbacks
* @since 4.5
*
* Registers callbacks to be called at different phases of the main loop.
*
* @param p_library A pointer the library received by the GDExtension's entry point function.
* @param p_callbacks A pointer to the structure that contains the callbacks.
*/
typedef void (*GDExtensionInterfaceRegisterMainLoopCallbacks)(GDExtensionClassLibraryPtr p_library, const GDExtensionMainLoopCallbacks *p_callbacks);
#ifdef __cplusplus
}
#endif
#endif // GDEXTENSION_INTERFACE_H

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_EDITOR_PLUGIN_REGISTRATION_HPP
#define GODOT_EDITOR_PLUGIN_REGISTRATION_HPP
#include <godot_cpp/templates/vector.hpp>
@@ -57,3 +58,5 @@ public:
};
} // namespace godot
#endif // GODOT_EDITOR_PLUGIN_REGISTRATION_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_REF_HPP
#define GODOT_REF_HPP
#include <godot_cpp/core/defs.hpp>
@@ -70,10 +71,6 @@ class Ref {
}
public:
static _FORCE_INLINE_ String get_class_static() {
return T::get_class_static();
}
_FORCE_INLINE_ bool operator==(const T *p_ptr) const {
return reference == p_ptr;
}
@@ -287,3 +284,5 @@ struct GetTypeInfo<const Ref<T> &, typename EnableIf<TypeInherits<RefCounted, T>
};
} // namespace godot
#endif // GODOT_REF_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_WRAPPED_HPP
#define GODOT_WRAPPED_HPP
#include <godot_cpp/core/memory.hpp>
@@ -110,8 +111,9 @@ protected:
::godot::List<::godot::PropertyInfo> plist_owned;
void _postinitialize();
virtual void _notificationv(int32_t p_what, bool p_reversed = false) {}
Wrapped(const StringName &p_godot_class);
Wrapped(const StringName p_godot_class);
Wrapped(GodotObject *p_godot_object);
virtual ~Wrapped() {}
@@ -188,9 +190,7 @@ private:
friend class ::godot::Wrapped; \
\
protected: \
virtual bool _is_extension_class() const override { \
return true; \
} \
virtual bool _is_extension_class() const override { return true; } \
\
static const ::godot::StringName *_get_extension_class_name() { \
const ::godot::StringName &string_name = get_class_static(); \
@@ -202,35 +202,35 @@ protected:
} \
\
static void (::godot::Wrapped::*_get_notification())(int) { \
return (void (::godot::Wrapped::*)(int)) & m_class::_notification; \
return (void(::godot::Wrapped::*)(int)) & m_class::_notification; \
} \
\
static bool (::godot::Wrapped::*_get_set())(const ::godot::StringName &p_name, const ::godot::Variant &p_property) { \
return (bool (::godot::Wrapped::*)(const ::godot::StringName &p_name, const ::godot::Variant &p_property)) & m_class::_set; \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, const ::godot::Variant &p_property)) & m_class::_set; \
} \
\
static bool (::godot::Wrapped::*_get_get())(const ::godot::StringName &p_name, ::godot::Variant &r_ret) const { \
return (bool (::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &r_ret) const) & m_class::_get; \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &r_ret) const) & m_class::_get; \
} \
\
static void (::godot::Wrapped::*_get_get_property_list())(::godot::List<::godot::PropertyInfo> * p_list) const { \
return (void (::godot::Wrapped::*)(::godot::List<::godot::PropertyInfo> * p_list) const) & m_class::_get_property_list; \
return (void(::godot::Wrapped::*)(::godot::List<::godot::PropertyInfo> * p_list) const) & m_class::_get_property_list; \
} \
\
static bool (::godot::Wrapped::*_get_property_can_revert())(const ::godot::StringName &p_name) const { \
return (bool (::godot::Wrapped::*)(const ::godot::StringName &p_name) const) & m_class::_property_can_revert; \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name) const) & m_class::_property_can_revert; \
} \
\
static bool (::godot::Wrapped::*_get_property_get_revert())(const ::godot::StringName &p_name, ::godot::Variant &) const { \
return (bool (::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &) const) & m_class::_property_get_revert; \
return (bool(::godot::Wrapped::*)(const ::godot::StringName &p_name, ::godot::Variant &) const) & m_class::_property_get_revert; \
} \
\
static void (::godot::Wrapped::*_get_validate_property())(::godot::PropertyInfo & p_property) const { \
return (void (::godot::Wrapped::*)(::godot::PropertyInfo & p_property) const) & m_class::_validate_property; \
return (void(::godot::Wrapped::*)(::godot::PropertyInfo & p_property) const) & m_class::_validate_property; \
} \
\
static ::godot::String (::godot::Wrapped::*_get_to_string())() const { \
return (::godot::String (::godot::Wrapped::*)() const) & m_class::_to_string; \
return (::godot::String(::godot::Wrapped::*)() const) & m_class::_to_string; \
} \
\
template <typename T, typename B> \
@@ -256,7 +256,7 @@ public:
} \
\
static const ::godot::StringName &get_class_static() { \
static const ::godot::StringName string_name = ::godot::StringName(U## #m_class); \
static const ::godot::StringName string_name = ::godot::StringName(#m_class); \
return string_name; \
} \
\
@@ -404,6 +404,11 @@ public:
_gde_binding_reference_callback, \
}; \
\
protected: \
virtual void _notificationv(int32_t p_what, bool p_reversed = false) override { \
m_class::notification_bind(this, p_what, p_reversed); \
} \
\
private:
// Don't use this for your classes, use GDCLASS() instead.
@@ -502,9 +507,14 @@ private:
// Don't use this for your classes, use GDCLASS() instead.
#define GDEXTENSION_CLASS(m_class, m_inherits) GDEXTENSION_CLASS_ALIAS(m_class, m_class, m_inherits)
#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__)
#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call(__VA_ARGS__)
#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call<false>(__VA_ARGS__)
#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<false>(__VA_ARGS__)
#define GDVIRTUAL_REQUIRED_CALL(m_name, ...) _gdvirtual_##m_name##_call<true>(__VA_ARGS__)
#define GDVIRTUAL_REQUIRED_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<true>(__VA_ARGS__)
#define GDVIRTUAL_BIND(m_name, ...) ::godot::ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info(), ::godot::snarray(__VA_ARGS__));
#define GDVIRTUAL_IS_OVERRIDDEN(m_name) _gdvirtual_##m_name##_overridden()
#define GDVIRTUAL_IS_OVERRIDDEN_PTR(m_obj, m_name) m_obj->_gdvirtual_##m_name##_overridden()
#endif // GODOT_WRAPPED_HPP

View File

@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_BINDER_COMMON_HPP
#define GODOT_BINDER_COMMON_HPP
#include <gdextension_interface.h>
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/core/method_ptrcall.hpp>
#include <godot_cpp/core/type_info.hpp>
@@ -692,3 +692,5 @@ void call_with_ptr_args_static_method_ret(R (*p_method)(P...), const GDExtension
#include <godot_cpp/classes/global_constants_binds.hpp>
#include <godot_cpp/variant/builtin_binds.hpp>
#endif // GODOT_BINDER_COMMON_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_BUILTIN_PTRCALL_HPP
#define GODOT_BUILTIN_PTRCALL_HPP
#include <gdextension_interface.h>
#include <godot_cpp/core/object.hpp>
@@ -87,3 +88,5 @@ T _call_builtin_ptr_getter(const GDExtensionPtrGetter getter, GDExtensionConstTy
} // namespace internal
} // namespace godot
#endif // GODOT_BUILTIN_PTRCALL_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_CLASS_DB_HPP
#define GODOT_CLASS_DB_HPP
#include <gdextension_interface.h>
@@ -47,6 +48,7 @@
#include <list>
#include <mutex>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>
@@ -86,17 +88,12 @@ class ClassDB {
public:
struct ClassInfo {
struct VirtualMethod {
GDExtensionClassCallVirtual func;
uint32_t hash;
};
StringName name;
StringName parent_name;
GDExtensionInitializationLevel level = GDEXTENSION_INITIALIZATION_SCENE;
std::unordered_map<StringName, MethodBind *> method_map;
std::set<StringName> signal_names;
std::unordered_map<StringName, VirtualMethod> virtual_methods;
std::unordered_map<StringName, GDExtensionClassCallVirtual> virtual_methods;
std::set<StringName> property_names;
std::set<StringName> constant_names;
// Pointer to the parent custom class, if any. Will be null if the parent class is a Godot class.
@@ -120,13 +117,9 @@ private:
static void _register_class(bool p_virtual = false, bool p_exposed = true, bool p_runtime = false);
template <typename T>
static GDExtensionObjectPtr _create_instance_func(void *data, GDExtensionBool p_notify_postinitialize) {
static GDExtensionObjectPtr _create_instance_func(void *data) {
if constexpr (!std::is_abstract_v<T>) {
Wrapped::_set_construct_info<T>();
T *new_object = new ("", "") T;
if (p_notify_postinitialize) {
new_object->_postinitialize();
}
T *new_object = memnew(T);
return new_object->_owner;
} else {
return nullptr;
@@ -166,8 +159,6 @@ public:
instance_binding_callbacks[p_name] = p_callbacks;
}
static void _editor_get_classes_used_callback(GDExtensionTypePtr p_packed_string_array);
static void _register_engine_singleton(const StringName &p_class_name, Object *p_singleton) {
std::lock_guard<std::mutex> lock(engine_singletons_mutex);
std::unordered_map<StringName, Object *>::const_iterator i = engine_singletons.find(p_class_name);
@@ -198,13 +189,13 @@ public:
static void add_signal(const StringName &p_class, const MethodInfo &p_signal);
static void bind_integer_constant(const StringName &p_class_name, const StringName &p_enum_name, const StringName &p_constant_name, GDExtensionInt p_constant_value, bool p_is_bitfield = false);
// Binds an implementation of a virtual method defined in Godot.
static void bind_virtual_method(const StringName &p_class, const StringName &p_method, GDExtensionClassCallVirtual p_call, uint32_t p_hash);
static void bind_virtual_method(const StringName &p_class, const StringName &p_method, GDExtensionClassCallVirtual p_call);
// Add a new virtual method that can be implemented by scripts.
static void add_virtual_method(const StringName &p_class, const MethodInfo &p_method, const Vector<StringName> &p_arg_names = Vector<StringName>());
static MethodBind *get_method(const StringName &p_class, const StringName &p_method);
static GDExtensionClassCallVirtual get_virtual_func(void *p_userdata, GDExtensionConstStringNamePtr p_name, uint32_t p_hash);
static GDExtensionClassCallVirtual get_virtual_func(void *p_userdata, GDExtensionConstStringNamePtr p_name);
static const GDExtensionInstanceBindingCallbacks *get_instance_binding_callbacks(const StringName &p_class);
static void initialize(GDExtensionInitializationLevel p_level);
@@ -222,12 +213,12 @@ public:
#define BIND_BITFIELD_FLAG(m_constant) \
::godot::ClassDB::bind_integer_constant(get_class_static(), ::godot::_gde_constant_get_bitfield_name(m_constant, #m_constant), #m_constant, m_constant, true);
#define BIND_VIRTUAL_METHOD(m_class, m_method, m_hash) \
#define BIND_VIRTUAL_METHOD(m_class, m_method) \
{ \
auto _call##m_method = [](GDExtensionObjectPtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr p_ret) -> void { \
call_with_ptr_args(reinterpret_cast<m_class *>(p_instance), &m_class::m_method, p_args, p_ret); \
}; \
::godot::ClassDB::bind_virtual_method(m_class::get_class_static(), #m_method, _call##m_method, m_hash); \
::godot::ClassDB::bind_virtual_method(m_class::get_class_static(), #m_method, _call##m_method); \
}
template <typename T, bool is_abstract>
@@ -251,12 +242,11 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_runtime) {
class_register_order.push_back(cl.name);
// Register this class with Godot
GDExtensionClassCreationInfo5 class_info = {
GDExtensionClassCreationInfo3 class_info = {
p_virtual, // GDExtensionBool is_virtual;
is_abstract, // GDExtensionBool is_abstract;
p_exposed, // GDExtensionBool is_exposed;
p_runtime, // GDExtensionBool is_runtime;
nullptr, // GDExtensionConstStringPtr icon_path;
T::set_bind, // GDExtensionClassSet set_func;
T::get_bind, // GDExtensionClassGet get_func;
T::has_get_property_list() ? T::get_property_list_bind : nullptr, // GDExtensionClassGetPropertyList get_property_list_func;
@@ -274,10 +264,11 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_runtime) {
&ClassDB::get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
nullptr, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
nullptr, // GDExtensionClassCallVirtualWithData call_virtual_func;
nullptr, // GDExtensionClassGetRID get_rid;
(void *)&T::get_class_static(), // void *class_userdata;
};
internal::gdextension_interface_classdb_register_extension_class5(internal::library, cl.name._native_ptr(), cl.parent_name._native_ptr(), &class_info);
internal::gdextension_interface_classdb_register_extension_class3(internal::library, cl.name._native_ptr(), cl.parent_name._native_ptr(), &class_info);
// call bind_methods etc. to register all members of the class
T::initialize_class();
@@ -370,3 +361,5 @@ MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p
} // namespace godot
CLASSDB_SINGLETON_VARIANT_CAST;
#endif // GODOT_CLASS_DB_HPP

View File

@@ -28,12 +28,12 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_DEFS_HPP
#define GODOT_DEFS_HPP
#include <cstddef>
#include <cstdint>
#include <type_traits>
#include <utility>
#include <cstring>
namespace godot {
@@ -65,33 +65,15 @@ namespace godot {
#endif
#endif
// Should always inline, except in dev builds because it makes debugging harder,
// or `size_enabled` builds where inlining is actively avoided.
// Should always inline, except in debug builds because it makes debugging harder.
#ifndef _FORCE_INLINE_
#if defined(DEV_ENABLED) || defined(SIZE_EXTRA)
#ifdef DISABLE_FORCED_INLINE
#define _FORCE_INLINE_ inline
#else
#define _FORCE_INLINE_ _ALWAYS_INLINE_
#endif
#endif
// Should never inline.
#ifndef _NO_INLINE_
#if defined(__GNUC__)
#define _NO_INLINE_ __attribute__((noinline))
#elif defined(_MSC_VER)
#define _NO_INLINE_ __declspec(noinline)
#else
#define _NO_INLINE_
#endif
#endif
// In some cases [[nodiscard]] will get false positives,
// we can prevent the warning in specific cases by preceding the call with a cast.
#ifndef _ALLOW_DISCARD_
#define _ALLOW_DISCARD_ (void)
#endif
// Windows badly defines a lot of stuff we'll never use. Undefine it.
#ifdef _WIN32
#undef min // override standard definition
@@ -99,182 +81,14 @@ namespace godot {
#undef ERROR // override (really stupid) wingdi.h standard definition
#undef DELETE // override (another really stupid) winnt.h standard definition
#undef MessageBox // override winuser.h standard definition
#undef MIN // override standard definition
#undef MAX // override standard definition
#undef CLAMP // override standard definition
#undef Error
#undef OK
#undef CONNECT_DEFERRED // override from Windows SDK, clashes with Object enum
#undef MemoryBarrier
#undef MONO_FONT
#endif
// Make room for our constexpr's below by overriding potential system-specific macros.
#undef SIGN
#undef MIN
#undef MAX
#undef CLAMP
template <typename T>
constexpr const T SIGN(const T m_v) {
return m_v > 0 ? +1.0f : (m_v < 0 ? -1.0f : 0.0f);
}
template <typename T, typename T2>
constexpr auto MIN(const T m_a, const T2 m_b) {
return m_a < m_b ? m_a : m_b;
}
template <typename T, typename T2>
constexpr auto MAX(const T m_a, const T2 m_b) {
return m_a > m_b ? m_a : m_b;
}
template <typename T, typename T2, typename T3>
constexpr auto CLAMP(const T m_a, const T2 m_min, const T3 m_max) {
return m_a < m_min ? m_min : (m_a > m_max ? m_max : m_a);
}
// Generic swap template.
#ifndef SWAP
#define SWAP(m_x, m_y) std::swap((m_x), (m_y))
#endif // SWAP
/* Functions to handle powers of 2 and shifting. */
// Returns `true` if a positive integer is a power of 2, `false` otherwise.
template <typename T>
inline bool is_power_of_2(const T x) {
return x && ((x & (x - 1)) == 0);
}
// Function to find the next power of 2 to an integer.
static _FORCE_INLINE_ unsigned int next_power_of_2(unsigned int x) {
if (x == 0) {
return 0;
}
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return ++x;
}
// Function to find the previous power of 2 to an integer.
static _FORCE_INLINE_ unsigned int previous_power_of_2(unsigned int x) {
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x - (x >> 1);
}
// Function to find the closest power of 2 to an integer.
static _FORCE_INLINE_ unsigned int closest_power_of_2(unsigned int x) {
unsigned int nx = next_power_of_2(x);
unsigned int px = previous_power_of_2(x);
return (nx - x) > (x - px) ? px : nx;
}
// Get a shift value from a power of 2.
static inline int get_shift_from_power_of_2(unsigned int p_bits) {
for (unsigned int i = 0; i < 32; i++) {
if (p_bits == (unsigned int)(1 << i)) {
return i;
}
}
return -1;
}
template <typename T>
static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) {
--x;
// The number of operations on x is the base two logarithm
// of the number of bits in the type. Add three to account
// for sizeof(T) being in bytes.
size_t num = get_shift_from_power_of_2(sizeof(T)) + 3;
// If the compiler is smart, it unrolls this loop.
// If it's dumb, this is a bit slow.
for (size_t i = 0; i < num; i++) {
x |= x >> (1 << i);
}
return ++x;
}
// Function to find the nearest (bigger) power of 2 to an integer.
static inline unsigned int nearest_shift(unsigned int p_number) {
for (int i = 30; i >= 0; i--) {
if (p_number & (1 << i)) {
return i + 1;
}
}
return 0;
}
// constexpr function to find the floored log2 of a number
template <typename T>
constexpr T floor_log2(T x) {
return x < 2 ? x : 1 + floor_log2(x >> 1);
}
// Get the number of bits needed to represent the number.
// IE, if you pass in 8, you will get 4.
// If you want to know how many bits are needed to store 8 values however, pass in (8 - 1).
template <typename T>
constexpr T get_num_bits(T x) {
return floor_log2(x);
}
// Swap 16, 32 and 64 bits value for endianness.
#if defined(__GNUC__)
#define BSWAP16(x) __builtin_bswap16(x)
#define BSWAP32(x) __builtin_bswap32(x)
#define BSWAP64(x) __builtin_bswap64(x)
#elif defined(_MSC_VER)
#define BSWAP16(x) _byteswap_ushort(x)
#define BSWAP32(x) _byteswap_ulong(x)
#define BSWAP64(x) _byteswap_uint64(x)
#else
static inline uint16_t BSWAP16(uint16_t x) {
return (x >> 8) | (x << 8);
}
static inline uint32_t BSWAP32(uint32_t x) {
return ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24));
}
static inline uint64_t BSWAP64(uint64_t x) {
x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8;
return x;
}
#endif
// Generic comparator used in Map, List, etc.
template <typename T>
struct Comparator {
_ALWAYS_INLINE_ bool operator()(const T &p_a, const T &p_b) const { return (p_a < p_b); }
};
// Global lock macro, relies on the static Mutex::_global_mutex.
void _global_lock();
void _global_unlock();
struct _GlobalLock {
_GlobalLock() { _global_lock(); }
~_GlobalLock() { _global_unlock(); }
};
#define GLOBAL_LOCK_FUNCTION _GlobalLock _global_lock_;
#if defined(__GNUC__)
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
@@ -283,17 +97,22 @@ struct _GlobalLock {
#define unlikely(x) x
#endif
#if defined(__GNUC__)
#define _PRINTF_FORMAT_ATTRIBUTE_2_0 __attribute__((format(printf, 2, 0)))
#define _PRINTF_FORMAT_ATTRIBUTE_2_3 __attribute__((format(printf, 2, 3)))
#ifdef REAL_T_IS_DOUBLE
typedef double real_t;
#else
#define _PRINTF_FORMAT_ATTRIBUTE_2_0
#define _PRINTF_FORMAT_ATTRIBUTE_2_3
typedef float real_t;
#endif
// This is needed due to a strange OpenGL API that expects a pointer
// type for an argument that is actually an offset.
#define CAST_INT_TO_UCHAR_PTR(ptr) ((uint8_t *)(uintptr_t)(ptr))
// Generic swap template.
#ifndef SWAP
#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y))
template <typename T>
inline void __swap_tmpl(T &x, T &y) {
T aux = x;
x = y;
y = aux;
}
#endif // SWAP
// Home-made index sequence trick, so it can be used everywhere without the costly include of std::tuple.
// https://stackoverflow.com/questions/15014096/c-index-of-type-during-variadic-template-expansion
@@ -306,36 +125,10 @@ struct BuildIndexSequence : BuildIndexSequence<N - 1, N - 1, Is...> {};
template <size_t... Is>
struct BuildIndexSequence<0, Is...> : IndexSequence<Is...> {};
// Limit the depth of recursive algorithms when dealing with Array/Dictionary
#define MAX_RECURSION 100
#ifdef DEBUG_ENABLED
#define DEBUG_METHODS_ENABLED
#endif
// Macro GD_IS_DEFINED() allows to check if a macro is defined. It needs to be defined to anything (say 1) to work.
#define __GDARG_PLACEHOLDER_1 false,
#define __gd_take_second_arg(__ignored, val, ...) val
#define ____gd_is_defined(arg1_or_junk) __gd_take_second_arg(arg1_or_junk true, false)
#define ___gd_is_defined(val) ____gd_is_defined(__GDARG_PLACEHOLDER_##val)
#define GD_IS_DEFINED(x) ___gd_is_defined(x)
// Whether the default value of a type is just all-0 bytes.
// This can most commonly be exploited by using memset for these types instead of loop-construct.
// Trivially constructible types are also zero-constructible.
template <typename T>
struct is_zero_constructible : std::is_trivially_constructible<T> {};
template <typename T>
struct is_zero_constructible<const T> : is_zero_constructible<T> {};
template <typename T>
struct is_zero_constructible<volatile T> : is_zero_constructible<T> {};
template <typename T>
struct is_zero_constructible<const volatile T> : is_zero_constructible<T> {};
template <typename T>
inline constexpr bool is_zero_constructible_v = is_zero_constructible<T>::value;
} //namespace godot
// To maintain compatibility an alias is defined outside the namespace.
// Consider it deprecated.
using real_t = godot::real_t;
#endif // GODOT_DEFS_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_ENGINE_PTRCALL_HPP
#define GODOT_ENGINE_PTRCALL_HPP
#include <gdextension_interface.h>
@@ -92,3 +93,5 @@ void _call_utility_no_ret(const GDExtensionPtrUtilityFunction func, const Args &
} // namespace internal
} // namespace godot
#endif // GODOT_ENGINE_PTRCALL_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_ERROR_MACROS_HPP
#define GODOT_ERROR_MACROS_HPP
#include <godot_cpp/core/defs.hpp>
@@ -801,3 +802,5 @@ void _err_flush_stdout();
#define CHECK_METHOD_BIND_RET(m_mb, m_ret)
#define CHECK_METHOD_BIND(m_mb)
#endif
#endif // GODOT_ERROR_MACROS_HPP

View File

@@ -1,51 +0,0 @@
/**************************************************************************/
/* math.compat.inc */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef DISABLE_DEPRECATED
namespace godot {
#undef ABS
// Generic ABS function, for math uses please use Math::abs.
template <typename T>
[[deprecated("Use Math::abs instead")]]
constexpr T ABS(T m_v) {
return m_v < 0 ? -m_v : m_v;
}
}
// To maintain compatibility an alias is defined outside the namespace.
// Consider it deprecated.
using real_t = godot::real_t;
#endif

View File

@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_MATH_HPP
#define GODOT_MATH_HPP
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/core/math_defs.hpp>
#include <gdextension_interface.h>
@@ -39,8 +39,185 @@
namespace godot {
#define Math_SQRT12 0.7071067811865475244008443621048490
#define Math_SQRT2 1.4142135623730950488016887242
#define Math_LN2 0.6931471805599453094172321215
#define Math_PI 3.1415926535897932384626433833
#define Math_TAU 6.2831853071795864769252867666
#define Math_E 2.7182818284590452353602874714
#define Math_INF INFINITY
#define Math_NAN NAN
// Make room for our constexpr's below by overriding potential system-specific macros.
#undef ABS
#undef SIGN
#undef MIN
#undef MAX
#undef CLAMP
// Generic ABS function, for math uses please use Math::abs.
template <typename T>
constexpr T ABS(T m_v) {
return m_v < 0 ? -m_v : m_v;
}
template <typename T>
constexpr const T SIGN(const T m_v) {
return m_v == 0 ? 0.0f : (m_v < 0 ? -1.0f : +1.0f);
}
template <typename T, typename T2>
constexpr auto MIN(const T m_a, const T2 m_b) {
return m_a < m_b ? m_a : m_b;
}
template <typename T, typename T2>
constexpr auto MAX(const T m_a, const T2 m_b) {
return m_a > m_b ? m_a : m_b;
}
template <typename T, typename T2, typename T3>
constexpr auto CLAMP(const T m_a, const T2 m_min, const T3 m_max) {
return m_a < m_min ? m_min : (m_a > m_max ? m_max : m_a);
}
// Generic swap template.
#ifndef SWAP
#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y))
template <typename T>
inline void __swap_tmpl(T &x, T &y) {
T aux = x;
x = y;
y = aux;
}
#endif // SWAP
/* Functions to handle powers of 2 and shifting. */
// Function to find the next power of 2 to an integer.
static _FORCE_INLINE_ unsigned int next_power_of_2(unsigned int x) {
if (x == 0) {
return 0;
}
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return ++x;
}
// Function to find the previous power of 2 to an integer.
static _FORCE_INLINE_ unsigned int previous_power_of_2(unsigned int x) {
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x - (x >> 1);
}
// Function to find the closest power of 2 to an integer.
static _FORCE_INLINE_ unsigned int closest_power_of_2(unsigned int x) {
unsigned int nx = next_power_of_2(x);
unsigned int px = previous_power_of_2(x);
return (nx - x) > (x - px) ? px : nx;
}
// Get a shift value from a power of 2.
static inline int get_shift_from_power_of_2(unsigned int p_bits) {
for (unsigned int i = 0; i < 32; i++) {
if (p_bits == (unsigned int)(1 << i)) {
return i;
}
}
return -1;
}
template <typename T>
static _FORCE_INLINE_ T nearest_power_of_2_templated(T x) {
--x;
// The number of operations on x is the base two logarithm
// of the number of bits in the type. Add three to account
// for sizeof(T) being in bytes.
size_t num = get_shift_from_power_of_2(sizeof(T)) + 3;
// If the compiler is smart, it unrolls this loop.
// If it's dumb, this is a bit slow.
for (size_t i = 0; i < num; i++) {
x |= x >> (1 << i);
}
return ++x;
}
// Function to find the nearest (bigger) power of 2 to an integer.
static inline unsigned int nearest_shift(unsigned int p_number) {
for (int i = 30; i >= 0; i--) {
if (p_number & (1 << i)) {
return i + 1;
}
}
return 0;
}
// constexpr function to find the floored log2 of a number
template <typename T>
constexpr T floor_log2(T x) {
return x < 2 ? x : 1 + floor_log2(x >> 1);
}
// Get the number of bits needed to represent the number.
// IE, if you pass in 8, you will get 4.
// If you want to know how many bits are needed to store 8 values however, pass in (8 - 1).
template <typename T>
constexpr T get_num_bits(T x) {
return floor_log2(x);
}
// Swap 16, 32 and 64 bits value for endianness.
#if defined(__GNUC__)
#define BSWAP16(x) __builtin_bswap16(x)
#define BSWAP32(x) __builtin_bswap32(x)
#define BSWAP64(x) __builtin_bswap64(x)
#else
static inline uint16_t BSWAP16(uint16_t x) {
return (x >> 8) | (x << 8);
}
static inline uint32_t BSWAP32(uint32_t x) {
return ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24));
}
static inline uint64_t BSWAP64(uint64_t x) {
x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8;
return x;
}
#endif
namespace Math {
// This epsilon should match the one used by Godot for consistency.
// Using `f` when `real_t` is float.
#define CMP_EPSILON 0.00001f
#define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON)
// This epsilon is for values related to a unit size (scalar or vector len).
#ifdef PRECISE_MATH_CHECKS
#define UNIT_EPSILON 0.00001
#else
// Tolerate some more floating point error normally.
#define UNIT_EPSILON 0.001
#endif
// Functions reproduced as in Godot's source code `math_funcs.h`.
// Some are overloads to automatically support changing real_t into either double or float in the way Godot does.
@@ -361,26 +538,6 @@ inline float bezier_interpolate(float p_start, float p_control_1, float p_contro
return p_start * omt3 + p_control_1 * omt2 * p_t * 3.0f + p_control_2 * omt * t2 * 3.0f + p_end * t3;
}
inline double bezier_derivative(double p_start, double p_control_1, double p_control_2, double p_end, double p_t) {
/* Formula from Wikipedia article on Bezier curves. */
double omt = (1.0 - p_t);
double omt2 = omt * omt;
double t2 = p_t * p_t;
double d = (p_control_1 - p_start) * 3.0 * omt2 + (p_control_2 - p_control_1) * 6.0 * omt * p_t + (p_end - p_control_2) * 3.0 * t2;
return d;
}
inline float bezier_derivative(float p_start, float p_control_1, float p_control_2, float p_end, float p_t) {
/* Formula from Wikipedia article on Bezier curves. */
float omt = (1.0f - p_t);
float omt2 = omt * omt;
float t2 = p_t * p_t;
float d = (p_control_1 - p_start) * 3.0f * omt2 + (p_control_2 - p_control_1) * 6.0f * omt * p_t + (p_end - p_control_2) * 3.0f * t2;
return d;
}
template <typename T>
inline T clamp(T x, T minv, T maxv) {
if (x < minv) {
@@ -659,4 +816,4 @@ inline float snap_scalar_separation(float p_offset, float p_step, float p_target
} // namespace Math
} // namespace godot
#include "math.compat.inc"
#endif // GODOT_MATH_HPP

View File

@@ -1,74 +0,0 @@
/**************************************************************************/
/* math_defs.hpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
namespace godot {
#define CMP_EPSILON 0.00001
#define CMP_EPSILON2 (CMP_EPSILON * CMP_EPSILON)
#define CMP_NORMALIZE_TOLERANCE 0.000001
#define CMP_POINT_IN_PLANE_EPSILON 0.00001
#define Math_SQRT12 0.7071067811865475244008443621048490
#define Math_SQRT2 1.4142135623730950488016887242
#define Math_LN2 0.6931471805599453094172321215
#define Math_TAU 6.2831853071795864769252867666
#define Math_PI 3.1415926535897932384626433833
#define Math_E 2.7182818284590452353602874714
#define Math_INF INFINITY
#define Math_NAN NAN
#ifdef DEBUG_ENABLED
#define MATH_CHECKS
#endif
//this epsilon is for values related to a unit size (scalar or vector len)
#ifdef PRECISE_MATH_CHECKS
#define UNIT_EPSILON 0.00001
#else
//tolerate some more floating point error normally
#define UNIT_EPSILON 0.001
#endif
#define USEC_TO_SEC(m_usec) ((m_usec) / 1000000.0)
/**
* The "Real" type is an abstract type used for real numbers, such as 1.5,
* in contrast to integer numbers. Precision can be controlled with the
* presence or absence of the REAL_T_IS_DOUBLE define.
*/
#ifdef REAL_T_IS_DOUBLE
typedef double real_t;
#else
typedef float real_t;
#endif
} // namespace godot

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_MEMORY_HPP
#define GODOT_MEMORY_HPP
#include <cstddef>
#include <cstdint>
@@ -101,6 +102,12 @@ _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
#define memnew_allocator(m_class, m_allocator) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", m_allocator::alloc) m_class))
#define memnew_placement(m_placement, m_class) (::godot::_pre_initialize<std::remove_pointer_t<decltype(new ("", "") m_class)>>(), ::godot::_post_initialize(new ("", m_placement, sizeof(m_class), "") m_class))
// Generic comparator used in Map, List, etc.
template <typename T>
struct Comparator {
_ALWAYS_INLINE_ bool operator()(const T &p_a, const T &p_b) const { return (p_a < p_b); }
};
template <typename T>
void memdelete(T *p_class, typename std::enable_if<!std::is_base_of_v<godot::Wrapped, T>>::type * = nullptr) {
if constexpr (!std::is_trivially_destructible_v<T>) {
@@ -209,3 +216,5 @@ struct _GlobalNilClass {
};
} // namespace godot
#endif // GODOT_MEMORY_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_METHOD_BIND_HPP
#define GODOT_METHOD_BIND_HPP
#include <godot_cpp/core/binder_common.hpp>
#include <godot_cpp/core/type_info.hpp>
@@ -39,8 +40,11 @@
#include <godot_cpp/classes/global_constants.hpp>
#include <string>
#include <vector>
#include <iostream>
namespace godot {
class MethodBind {
@@ -154,7 +158,8 @@ public:
template <typename Derived, typename T, typename R, bool should_returns>
class MethodBindVarArgBase : public MethodBind {
protected:
R (T::*method)(const Variant **, GDExtensionInt, GDExtensionCallError &);
R(T::*method)
(const Variant **, GDExtensionInt, GDExtensionCallError &);
std::vector<PropertyInfo> arguments;
public:
@@ -438,7 +443,8 @@ template <typename T, typename R, typename... P>
template <typename R, typename... P>
#endif // TYPED_METHOD_BIND
class MethodBindTR : public MethodBind {
R (MB_T::*method)(P...);
R(MB_T::*method)
(P...);
protected:
// GCC raises warnings in the case P = {} as the comparison is always false...
@@ -520,7 +526,8 @@ template <typename T, typename R, typename... P>
template <typename R, typename... P>
#endif // TYPED_METHOD_BIND
class MethodBindTRC : public MethodBind {
R (MB_T::*method)(P...) const;
R(MB_T::*method)
(P...) const;
protected:
// GCC raises warnings in the case P = {} as the comparison is always false...
@@ -665,7 +672,8 @@ MethodBind *create_static_method_bind(void (*p_method)(P...)) {
template <typename R, typename... P>
class MethodBindTRS : public MethodBind {
R (*function)(P...);
R(*function)
(P...);
protected:
// GCC raises warnings in the case P = {} as the comparison is always false...
@@ -731,3 +739,5 @@ MethodBind *create_static_method_bind(R (*p_method)(P...)) {
}
} // namespace godot
#endif // GODOT_METHOD_BIND_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_METHOD_PTRCALL_HPP
#define GODOT_METHOD_PTRCALL_HPP
#include <godot_cpp/core/defs.hpp>
@@ -236,3 +237,5 @@ GDVIRTUAL_NATIVE_PTR(float);
GDVIRTUAL_NATIVE_PTR(double);
} // namespace godot
#endif // GODOT_METHOD_PTRCALL_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_MUTEX_LOCK_HPP
#define GODOT_MUTEX_LOCK_HPP
#include <godot_cpp/classes/mutex.hpp>
@@ -54,3 +55,5 @@ public:
#define _THREAD_SAFE_UNLOCK_ _thread_safe_.unlock();
} // namespace godot
#endif // GODOT_MUTEX_LOCK_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_OBJECT_HPP
#define GODOT_OBJECT_HPP
#include <godot_cpp/core/defs.hpp>
@@ -147,3 +148,5 @@ const T *Object::cast_to(const Object *p_object) {
}
} // namespace godot
#endif // GODOT_OBJECT_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_OBJECT_ID_HPP
#define GODOT_OBJECT_ID_HPP
#include <godot_cpp/core/defs.hpp>
@@ -57,3 +58,5 @@ public:
};
} // namespace godot
#endif // GODOT_OBJECT_ID_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_PRINT_STRING_HPP
#define GODOT_PRINT_STRING_HPP
#include <godot_cpp/variant/utility_functions.hpp>
@@ -68,3 +69,5 @@ void print_verbose(const Variant &p_variant, Args... p_args) {
bool is_print_verbose_enabled();
} // namespace godot
#endif // GODOT_PRINT_STRING_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_PROPERTY_INFO_HPP
#define GODOT_PROPERTY_INFO_HPP
#include <godot_cpp/core/defs.hpp>
@@ -127,3 +128,5 @@ struct PropertyInfo {
};
} // namespace godot
#endif // GODOT_PROPERTY_INFO_HPP

View File

@@ -28,9 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_TYPE_INFO_HPP
#define GODOT_TYPE_INFO_HPP
#include <godot_cpp/core/method_ptrcall.hpp>
#include <godot_cpp/core/object.hpp>
#include <godot_cpp/variant/typed_array.hpp>
#include <godot_cpp/variant/variant.hpp>
@@ -148,8 +148,8 @@ MAKE_TYPE_INFO_WITH_META(uint32_t, GDEXTENSION_VARIANT_TYPE_INT, GDEXTENSION_MET
MAKE_TYPE_INFO_WITH_META(int32_t, GDEXTENSION_VARIANT_TYPE_INT, GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT32)
MAKE_TYPE_INFO_WITH_META(uint64_t, GDEXTENSION_VARIANT_TYPE_INT, GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64)
MAKE_TYPE_INFO_WITH_META(int64_t, GDEXTENSION_VARIANT_TYPE_INT, GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64)
MAKE_TYPE_INFO_WITH_META(char16_t, GDEXTENSION_VARIANT_TYPE_INT, GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_CHAR16)
MAKE_TYPE_INFO_WITH_META(char32_t, GDEXTENSION_VARIANT_TYPE_INT, GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_CHAR32)
MAKE_TYPE_INFO(char16_t, GDEXTENSION_VARIANT_TYPE_INT)
MAKE_TYPE_INFO(char32_t, GDEXTENSION_VARIANT_TYPE_INT)
MAKE_TYPE_INFO_WITH_META(float, GDEXTENSION_VARIANT_TYPE_FLOAT, GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT)
MAKE_TYPE_INFO_WITH_META(double, GDEXTENSION_VARIANT_TYPE_FLOAT, GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE)
@@ -416,3 +416,5 @@ MAKE_TYPED_ARRAY_INFO(IPAddress, Variant::STRING)
#define CLASS_INFO(m_type) (GetTypeInfo<m_type *>::get_class_info())
} // namespace godot
#endif // GODOT_TYPE_INFO_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_GODOT_HPP
#define GODOT_GODOT_HPP
#include <gdextension_interface.h>
@@ -40,10 +41,10 @@ extern "C" GDExtensionInterfaceGetProcAddress gdextension_interface_get_proc_add
extern "C" GDExtensionClassLibraryPtr library;
extern "C" void *token;
extern "C" GDExtensionGodotVersion2 godot_version;
extern "C" GDExtensionGodotVersion godot_version;
// All of the GDExtension interface functions.
extern "C" GDExtensionInterfaceGetGodotVersion2 gdextension_interface_get_godot_version2;
extern "C" GDExtensionInterfaceGetGodotVersion gdextension_interface_get_godot_version;
extern "C" GDExtensionInterfaceMemAlloc gdextension_interface_mem_alloc;
extern "C" GDExtensionInterfaceMemRealloc gdextension_interface_mem_realloc;
extern "C" GDExtensionInterfaceMemFree gdextension_interface_mem_free;
@@ -81,13 +82,11 @@ extern "C" GDExtensionInterfaceVariantGetType gdextension_interface_variant_get_
extern "C" GDExtensionInterfaceVariantHasMethod gdextension_interface_variant_has_method;
extern "C" GDExtensionInterfaceVariantHasMember gdextension_interface_variant_has_member;
extern "C" GDExtensionInterfaceVariantHasKey gdextension_interface_variant_has_key;
extern "C" GDExtensionInterfaceVariantGetObjectInstanceId gdextension_interface_variant_get_object_instance_id;
extern "C" GDExtensionInterfaceVariantGetTypeName gdextension_interface_variant_get_type_name;
extern "C" GDExtensionInterfaceVariantCanConvert gdextension_interface_variant_can_convert;
extern "C" GDExtensionInterfaceVariantCanConvertStrict gdextension_interface_variant_can_convert_strict;
extern "C" GDExtensionInterfaceGetVariantFromTypeConstructor gdextension_interface_get_variant_from_type_constructor;
extern "C" GDExtensionInterfaceGetVariantToTypeConstructor gdextension_interface_get_variant_to_type_constructor;
extern "C" GDExtensionInterfaceGetVariantGetInternalPtrFunc gdextension_interface_variant_get_ptr_internal_getter;
extern "C" GDExtensionInterfaceVariantGetPtrOperatorEvaluator gdextension_interface_variant_get_ptr_operator_evaluator;
extern "C" GDExtensionInterfaceVariantGetPtrBuiltinMethod gdextension_interface_variant_get_ptr_builtin_method;
extern "C" GDExtensionInterfaceVariantGetPtrConstructor gdextension_interface_variant_get_ptr_constructor;
@@ -155,10 +154,10 @@ extern "C" GDExtensionInterfacePackedVector4ArrayOperatorIndex gdextension_inter
extern "C" GDExtensionInterfacePackedVector4ArrayOperatorIndexConst gdextension_interface_packed_vector4_array_operator_index_const;
extern "C" GDExtensionInterfaceArrayOperatorIndex gdextension_interface_array_operator_index;
extern "C" GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const;
extern "C" GDExtensionInterfaceArrayRef gdextension_interface_array_ref;
extern "C" GDExtensionInterfaceArraySetTyped gdextension_interface_array_set_typed;
extern "C" GDExtensionInterfaceDictionaryOperatorIndex gdextension_interface_dictionary_operator_index;
extern "C" GDExtensionInterfaceDictionaryOperatorIndexConst gdextension_interface_dictionary_operator_index_const;
extern "C" GDExtensionInterfaceDictionarySetTyped gdextension_interface_dictionary_set_typed;
extern "C" GDExtensionInterfaceObjectMethodBindCall gdextension_interface_object_method_bind_call;
extern "C" GDExtensionInterfaceObjectMethodBindPtrcall gdextension_interface_object_method_bind_ptrcall;
extern "C" GDExtensionInterfaceObjectDestroy gdextension_interface_object_destroy;
@@ -180,12 +179,10 @@ extern "C" GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object
extern "C" GDExtensionInterfaceScriptInstanceCreate3 gdextension_interface_script_instance_create3;
extern "C" GDExtensionInterfacePlaceHolderScriptInstanceCreate gdextension_interface_placeholder_script_instance_create;
extern "C" GDExtensionInterfacePlaceHolderScriptInstanceUpdate gdextension_interface_placeholder_script_instance_update;
extern "C" GDExtensionInterfaceObjectGetScriptInstance gdextension_interface_object_get_script_instance;
extern "C" GDExtensionInterfaceObjectSetScriptInstance gdextension_interface_object_set_script_instance;
extern "C" GDExtensionInterfaceClassdbConstructObject2 gdextension_interface_classdb_construct_object2;
extern "C" GDExtensionInterfaceClassdbConstructObject gdextension_interface_classdb_construct_object;
extern "C" GDExtensionInterfaceClassdbGetMethodBind gdextension_interface_classdb_get_method_bind;
extern "C" GDExtensionInterfaceClassdbGetClassTag gdextension_interface_classdb_get_class_tag;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClass5 gdextension_interface_classdb_register_extension_class5;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClass3 gdextension_interface_classdb_register_extension_class3;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod gdextension_interface_classdb_register_extension_class_virtual_method;
extern "C" GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant;
@@ -198,12 +195,10 @@ extern "C" GDExtensionInterfaceClassdbUnregisterExtensionClass gdextension_inter
extern "C" GDExtensionInterfaceGetLibraryPath gdextension_interface_get_library_path;
extern "C" GDExtensionInterfaceEditorAddPlugin gdextension_interface_editor_add_plugin;
extern "C" GDExtensionInterfaceEditorRemovePlugin gdextension_interface_editor_remove_plugin;
extern "C" GDExtensionInterfaceEditorRegisterGetClassesUsedCallback gdextension_interface_editor_register_get_classes_used_callback;
extern "C" GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars gdextension_interface_editor_help_load_xml_from_utf8_chars;
extern "C" GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen gdextension_interface_editor_help_load_xml_from_utf8_chars_and_len;
extern "C" GDExtensionInterfaceImagePtrw gdextension_interface_image_ptrw;
extern "C" GDExtensionInterfaceImagePtr gdextension_interface_image_ptr;
extern "C" GDExtensionInterfaceRegisterMainLoopCallbacks gdextension_interface_register_main_loop_callbacks;
class DocDataRegistration {
public:
@@ -228,11 +223,6 @@ public:
GDExtensionInitializationLevel minimum_initialization_level = GDEXTENSION_INITIALIZATION_CORE;
Callback init_callback = nullptr;
Callback terminate_callback = nullptr;
GDExtensionMainLoopCallbacks main_loop_callbacks = {};
inline bool has_main_loop_callbacks() const {
return main_loop_callbacks.frame_func || main_loop_callbacks.startup_func || main_loop_callbacks.shutdown_func;
}
};
class InitDataList {
@@ -267,15 +257,10 @@ public:
void register_terminator(Callback p_init) const;
void set_minimum_library_initialization_level(ModuleInitializationLevel p_level) const;
// Register a callback that is called after all initialization levels when Godot is fully initialized.
void register_startup_callback(GDExtensionMainLoopStartupCallback p_callback) const;
// Register a callback that is called for every process frame. This will run after all `_process()` methods on Node, and before `ScriptServer::frame()`.
void register_frame_callback(GDExtensionMainLoopFrameCallback p_callback) const;
// Register a callback that is called before Godot is shutdown when it is still fully initialized.
void register_shutdown_callback(GDExtensionMainLoopShutdownCallback p_callback) const;
GDExtensionBool init() const;
};
};
} // namespace godot
#endif // GODOT_GODOT_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_COWDATA_HPP
#define GODOT_COWDATA_HPP
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/core/error_macros.hpp>
@@ -37,10 +38,8 @@
#include <godot_cpp/templates/safe_refcount.hpp>
#include <cstring>
#include <initializer_list>
#include <new>
#include <type_traits>
#include <utility>
namespace godot {
@@ -168,25 +167,13 @@ private:
return *out;
}
// Decrements the reference count. Deallocates the backing buffer if needed.
// After this function, _ptr is guaranteed to be NULL.
void _unref();
void _unref(void *p_data);
void _ref(const CowData *p_from);
void _ref(const CowData &p_from);
USize _copy_on_write();
Error _realloc(Size p_alloc_size);
public:
void operator=(const CowData<T> &p_from) { _ref(p_from); }
void operator=(CowData<T> &&p_from) {
if (_ptr == p_from._ptr) {
return;
}
_unref();
_ptr = p_from._ptr;
p_from._ptr = nullptr;
}
_FORCE_INLINE_ T *ptrw() {
_copy_on_write();
@@ -235,22 +222,19 @@ public:
T *p = ptrw();
Size len = size();
for (Size i = p_index; i < len - 1; i++) {
p[i] = std::move(p[i + 1]);
p[i] = p[i + 1];
}
resize(len - 1);
}
Error insert(Size p_pos, const T &p_val) {
Size new_size = size() + 1;
ERR_FAIL_INDEX_V(p_pos, new_size, ERR_INVALID_PARAMETER);
Error err = resize(new_size);
ERR_FAIL_COND_V(err, err);
T *p = ptrw();
for (Size i = new_size - 1; i > p_pos; i--) {
p[i] = std::move(p[i - 1]);
ERR_FAIL_INDEX_V(p_pos, size() + 1, ERR_INVALID_PARAMETER);
resize(size() + 1);
for (Size i = (size() - 1); i > p_pos; i--) {
set(i, get(i - 1));
}
p[p_pos] = p_val;
set(p_pos, p_val);
return OK;
}
@@ -260,47 +244,35 @@ public:
Size count(const T &p_val) const;
_FORCE_INLINE_ CowData() {}
_FORCE_INLINE_ ~CowData() { _unref(); }
_FORCE_INLINE_ CowData(std::initializer_list<T> p_init);
_FORCE_INLINE_ CowData(const CowData<T> &p_from) { _ref(p_from); }
_FORCE_INLINE_ CowData(CowData<T> &&p_from) {
_ptr = p_from._ptr;
p_from._ptr = nullptr;
}
_FORCE_INLINE_ ~CowData();
_FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); };
};
template <typename T>
void CowData<T>::_unref() {
if (!_ptr) {
void CowData<T>::_unref(void *p_data) {
if (!p_data) {
return;
}
SafeNumeric<USize> *refc = _get_refcount();
if (refc->decrement() > 0) {
// Data is still in use elsewhere.
_ptr = nullptr;
return;
return; // still in use
}
// Clean up.
// First, invalidate our own reference.
// NOTE: It is required to do so immediately because it must not be observable outside of this
// function after refcount has already been reduced to 0.
// WARNING: It must be done before calling the destructors, because one of them may otherwise
// observe it through a reference to us. In this case, it may try to access the buffer,
// which is illegal after some of the elements in it have already been destructed, and
// may lead to a segmentation fault.
USize current_size = *_get_size();
T *prev_ptr = _ptr;
_ptr = nullptr;
// clean up
if constexpr (!std::is_trivially_destructible_v<T>) {
for (USize i = 0; i < current_size; ++i) {
prev_ptr[i].~T();
USize *count = _get_size();
T *data = (T *)(count + 1);
for (USize i = 0; i < *count; ++i) {
// call destructors
data[i].~T();
}
}
// free mem
Memory::free_static((uint8_t *)prev_ptr - DATA_OFFSET, false);
Memory::free_static(((uint8_t *)p_data) - DATA_OFFSET, false);
}
template <typename T>
@@ -335,7 +307,7 @@ typename CowData<T>::USize CowData<T>::_copy_on_write() {
}
}
_unref();
_unref(_ptr);
_ptr = _data_ptr;
rc = 1;
@@ -355,13 +327,14 @@ Error CowData<T>::resize(Size p_size) {
}
if (p_size == 0) {
// Wants to clean up.
_unref(); // Resets _ptr to nullptr.
// wants to clean up
_unref(_ptr);
_ptr = nullptr;
return OK;
}
// possibly changing size, copy on write
_copy_on_write();
USize rc = _copy_on_write();
USize current_alloc_size = _get_alloc_size(current_size);
USize alloc_size;
@@ -382,12 +355,16 @@ Error CowData<T>::resize(Size p_size) {
*(_size_ptr) = 0; //size, currently none
_ptr = _data_ptr;
} else {
const Error error = _realloc(alloc_size);
if (error) {
return error;
}
uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, alloc_size + DATA_OFFSET, false);
ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY);
SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new);
T *_data_ptr = _get_data_ptr(mem_new);
new (_refc_ptr) SafeNumeric<USize>(rc); //refcount
_ptr = _data_ptr;
}
}
@@ -413,10 +390,15 @@ Error CowData<T>::resize(Size p_size) {
}
if (alloc_size != current_alloc_size) {
const Error error = _realloc(alloc_size);
if (error) {
return error;
}
uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, alloc_size + DATA_OFFSET, false);
ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY);
SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new);
T *_data_ptr = _get_data_ptr(mem_new);
new (_refc_ptr) SafeNumeric<USize>(rc); //refcount
_ptr = _data_ptr;
}
*_get_size() = p_size;
@@ -425,21 +407,6 @@ Error CowData<T>::resize(Size p_size) {
return OK;
}
template <typename T>
Error CowData<T>::_realloc(Size p_alloc_size) {
uint8_t *mem_new = (uint8_t *)Memory::realloc_static(((uint8_t *)_ptr) - DATA_OFFSET, p_alloc_size + DATA_OFFSET, false);
ERR_FAIL_NULL_V(mem_new, ERR_OUT_OF_MEMORY);
SafeNumeric<USize> *_refc_ptr = _get_refcount_ptr(mem_new);
T *_data_ptr = _get_data_ptr(mem_new);
// If we realloc, we're guaranteed to be the only reference.
new (_refc_ptr) SafeNumeric<USize>(1);
_ptr = _data_ptr;
return OK;
}
template <typename T>
typename CowData<T>::Size CowData<T>::find(const T &p_val, Size p_from) const {
Size ret = -1;
@@ -499,10 +466,11 @@ void CowData<T>::_ref(const CowData &p_from) {
return; // self assign, do nothing.
}
_unref(); // Resets _ptr to nullptr.
_unref(_ptr);
_ptr = nullptr;
if (!p_from._ptr) {
return; //nothing to do
return; // nothing to do
}
if (p_from._get_refcount()->conditional_increment() > 0) { // could reference
@@ -511,16 +479,8 @@ void CowData<T>::_ref(const CowData &p_from) {
}
template <typename T>
CowData<T>::CowData(std::initializer_list<T> p_init) {
Error err = resize(p_init.size());
if (err != OK) {
return;
}
Size i = 0;
for (const T &element : p_init) {
set(i++, element);
}
CowData<T>::~CowData() {
_unref(_ptr);
}
#if defined(__GNUC__) && !defined(__clang__)
@@ -528,3 +488,5 @@ CowData<T>::CowData(std::initializer_list<T> p_init) {
#endif
} // namespace godot
#endif // GODOT_COWDATA_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_HASH_MAP_HPP
#define GODOT_HASH_MAP_HPP
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/memory.hpp>
@@ -61,17 +62,15 @@ struct HashMapElement {
data(p_key, p_value) {}
};
bool _hashmap_variant_less_than(const Variant &p_left, const Variant &p_right);
template <typename TKey, typename TValue,
typename Hasher = HashMapHasherDefault,
typename Comparator = HashMapComparatorDefault<TKey>,
typename Allocator = DefaultTypedAllocator<HashMapElement<TKey, TValue>>>
class HashMap {
public:
static constexpr uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime.
static constexpr float MAX_OCCUPANCY = 0.75;
static constexpr uint32_t EMPTY_HASH = 0;
const uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime.
const float MAX_OCCUPANCY = 0.75;
const uint32_t EMPTY_HASH = 0;
private:
Allocator element_alloc;
@@ -93,20 +92,19 @@ private:
return hash;
}
static _FORCE_INLINE_ uint32_t _get_probe_length(const uint32_t p_pos, const uint32_t p_hash, const uint32_t p_capacity, const uint64_t p_capacity_inv) {
const uint32_t original_pos = fastmod(p_hash, p_capacity_inv, p_capacity);
return fastmod(p_pos - original_pos + p_capacity, p_capacity_inv, p_capacity);
_FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash, uint32_t p_capacity) const {
uint32_t original_pos = p_hash % p_capacity;
return (p_pos - original_pos + p_capacity) % p_capacity;
}
bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) const {
if (elements == nullptr || num_elements == 0) {
if (elements == nullptr) {
return false; // Failed lookups, no elements
}
const uint32_t capacity = hash_table_size_primes[capacity_index];
const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index];
uint32_t capacity = hash_table_size_primes[capacity_index];
uint32_t hash = _hash(p_key);
uint32_t pos = fastmod(hash, capacity_inv, capacity);
uint32_t pos = hash % capacity;
uint32_t distance = 0;
while (true) {
@@ -114,7 +112,7 @@ private:
return false;
}
if (distance > _get_probe_length(pos, hashes[pos], capacity, capacity_inv)) {
if (distance > _get_probe_length(pos, hashes[pos], capacity)) {
return false;
}
@@ -123,18 +121,17 @@ private:
return true;
}
pos = fastmod((pos + 1), capacity_inv, capacity);
pos = (pos + 1) % capacity;
distance++;
}
}
void _insert_with_hash(uint32_t p_hash, HashMapElement<TKey, TValue> *p_value) {
const uint32_t capacity = hash_table_size_primes[capacity_index];
const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index];
uint32_t capacity = hash_table_size_primes[capacity_index];
uint32_t hash = p_hash;
HashMapElement<TKey, TValue> *value = p_value;
uint32_t distance = 0;
uint32_t pos = fastmod(hash, capacity_inv, capacity);
uint32_t pos = hash % capacity;
while (true) {
if (hashes[pos] == EMPTY_HASH) {
@@ -147,14 +144,14 @@ private:
}
// Not an empty slot, let's check the probing length of the existing one.
uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity, capacity_inv);
uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity);
if (existing_probe_len < distance) {
SWAP(hash, hashes[pos]);
SWAP(value, elements[pos]);
distance = existing_probe_len;
}
pos = fastmod((pos + 1), capacity_inv, capacity);
pos = (pos + 1) % capacity;
distance++;
}
}
@@ -254,7 +251,7 @@ public:
}
void clear() {
if (elements == nullptr || num_elements == 0) {
if (elements == nullptr) {
return;
}
uint32_t capacity = hash_table_size_primes[capacity_index];
@@ -273,47 +270,6 @@ public:
num_elements = 0;
}
void sort() {
if (elements == nullptr || num_elements < 2) {
return; // An empty or single element HashMap is already sorted.
}
// Use insertion sort because we want this operation to be fast for the
// common case where the input is already sorted or nearly sorted.
HashMapElement<TKey, TValue> *inserting = head_element->next;
while (inserting != nullptr) {
HashMapElement<TKey, TValue> *after = nullptr;
for (HashMapElement<TKey, TValue> *current = inserting->prev; current != nullptr; current = current->prev) {
if (_hashmap_variant_less_than(inserting->data.key, current->data.key)) {
after = current;
} else {
break;
}
}
HashMapElement<TKey, TValue> *next = inserting->next;
if (after != nullptr) {
// Modify the elements around `inserting` to remove it from its current position.
inserting->prev->next = next;
if (next == nullptr) {
tail_element = inserting->prev;
} else {
next->prev = inserting->prev;
}
// Modify `before` and `after` to insert `inserting` between them.
HashMapElement<TKey, TValue> *before = after->prev;
if (before == nullptr) {
head_element = inserting;
} else {
before->next = inserting;
}
after->prev = inserting;
// Point `inserting` to its new surroundings.
inserting->prev = before;
inserting->next = after;
}
inserting = next;
}
}
TValue &get(const TKey &p_key) {
uint32_t pos = 0;
bool exists = _lookup_pos(p_key, pos);
@@ -361,14 +317,13 @@ public:
return false;
}
const uint32_t capacity = hash_table_size_primes[capacity_index];
const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index];
uint32_t next_pos = fastmod((pos + 1), capacity_inv, capacity);
while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity, capacity_inv) != 0) {
uint32_t capacity = hash_table_size_primes[capacity_index];
uint32_t next_pos = (pos + 1) % capacity;
while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity) != 0) {
SWAP(hashes[next_pos], hashes[pos]);
SWAP(elements[next_pos], elements[pos]);
pos = next_pos;
next_pos = fastmod((pos + 1), capacity_inv, capacity);
next_pos = (pos + 1) % capacity;
}
hashes[pos] = EMPTY_HASH;
@@ -396,40 +351,6 @@ public:
return true;
}
// Replace the key of an entry in-place, without invalidating iterators or changing the entries position during iteration.
// p_old_key must exist in the map and p_new_key must not, unless it is equal to p_old_key.
bool replace_key(const TKey &p_old_key, const TKey &p_new_key) {
if (p_old_key == p_new_key) {
return true;
}
uint32_t pos = 0;
ERR_FAIL_COND_V(_lookup_pos(p_new_key, pos), false);
ERR_FAIL_COND_V(!_lookup_pos(p_old_key, pos), false);
HashMapElement<TKey, TValue> *element = elements[pos];
// Delete the old entries in hashes and elements.
const uint32_t capacity = hash_table_size_primes[capacity_index];
const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index];
uint32_t next_pos = fastmod((pos + 1), capacity_inv, capacity);
while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity, capacity_inv) != 0) {
SWAP(hashes[next_pos], hashes[pos]);
SWAP(elements[next_pos], elements[pos]);
pos = next_pos;
next_pos = fastmod((pos + 1), capacity_inv, capacity);
}
hashes[pos] = EMPTY_HASH;
elements[pos] = nullptr;
// _insert_with_hash will increment this again.
num_elements--;
// Update the HashMapElement with the new key and reinsert it.
const_cast<TKey &>(element->data.key) = p_new_key;
uint32_t hash = _hash(p_new_key);
_insert_with_hash(hash, element);
return true;
}
// Reserves space for a number of elements, useful to avoid many resizes and rehashes.
// If adding a known (possibly large) number of elements at once, must be larger than old capacity.
void reserve(uint32_t p_new_capacity) {
@@ -640,13 +561,6 @@ public:
capacity_index = MIN_CAPACITY_INDEX;
}
HashMap(std::initializer_list<KeyValue<TKey, TValue>> p_init) {
reserve(p_init.size());
for (const KeyValue<TKey, TValue> &E : p_init) {
insert(E.key, E.value);
}
}
uint32_t debug_get_hash(uint32_t p_index) {
if (num_elements == 0) {
return 0;
@@ -673,3 +587,5 @@ public:
};
} // namespace godot
#endif // GODOT_HASH_MAP_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_HASH_SET_HPP
#define GODOT_HASH_SET_HPP
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/memory.hpp>
@@ -75,20 +76,19 @@ private:
return hash;
}
static _FORCE_INLINE_ uint32_t _get_probe_length(const uint32_t p_pos, const uint32_t p_hash, const uint32_t p_capacity, const uint64_t p_capacity_inv) {
const uint32_t original_pos = fastmod(p_hash, p_capacity_inv, p_capacity);
return fastmod(p_pos - original_pos + p_capacity, p_capacity_inv, p_capacity);
_FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash, uint32_t p_capacity) const {
uint32_t original_pos = p_hash % p_capacity;
return (p_pos - original_pos + p_capacity) % p_capacity;
}
bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) const {
if (keys == nullptr || num_elements == 0) {
if (keys == nullptr) {
return false; // Failed lookups, no elements
}
const uint32_t capacity = hash_table_size_primes[capacity_index];
const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index];
uint32_t capacity = hash_table_size_primes[capacity_index];
uint32_t hash = _hash(p_key);
uint32_t pos = fastmod(hash, capacity_inv, capacity);
uint32_t pos = hash % capacity;
uint32_t distance = 0;
while (true) {
@@ -96,7 +96,7 @@ private:
return false;
}
if (distance > _get_probe_length(pos, hashes[pos], capacity, capacity_inv)) {
if (distance > _get_probe_length(pos, hashes[pos], capacity)) {
return false;
}
@@ -105,18 +105,17 @@ private:
return true;
}
pos = fastmod(pos + 1, capacity_inv, capacity);
pos = (pos + 1) % capacity;
distance++;
}
}
uint32_t _insert_with_hash(uint32_t p_hash, uint32_t p_index) {
const uint32_t capacity = hash_table_size_primes[capacity_index];
const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index];
uint32_t capacity = hash_table_size_primes[capacity_index];
uint32_t hash = p_hash;
uint32_t index = p_index;
uint32_t distance = 0;
uint32_t pos = fastmod(hash, capacity_inv, capacity);
uint32_t pos = hash % capacity;
while (true) {
if (hashes[pos] == EMPTY_HASH) {
@@ -127,7 +126,7 @@ private:
}
// Not an empty slot, let's check the probing length of the existing one.
uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity, capacity_inv);
uint32_t existing_probe_len = _get_probe_length(pos, hashes[pos], capacity);
if (existing_probe_len < distance) {
key_to_hash[index] = pos;
SWAP(hash, hashes[pos]);
@@ -135,7 +134,7 @@ private:
distance = existing_probe_len;
}
pos = fastmod(pos + 1, capacity_inv, capacity);
pos = (pos + 1) % capacity;
distance++;
}
}
@@ -238,7 +237,7 @@ public:
}
void clear() {
if (keys == nullptr || num_elements == 0) {
if (keys == nullptr) {
return;
}
uint32_t capacity = hash_table_size_primes[capacity_index];
@@ -266,12 +265,11 @@ public:
}
uint32_t key_pos = pos;
pos = key_to_hash[pos]; //make hash pos
pos = key_to_hash[pos]; // make hash pos
const uint32_t capacity = hash_table_size_primes[capacity_index];
const uint64_t capacity_inv = hash_table_size_primes_inv[capacity_index];
uint32_t next_pos = fastmod(pos + 1, capacity_inv, capacity);
while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity, capacity_inv) != 0) {
uint32_t capacity = hash_table_size_primes[capacity_index];
uint32_t next_pos = (pos + 1) % capacity;
while (hashes[next_pos] != EMPTY_HASH && _get_probe_length(next_pos, hashes[next_pos], capacity) != 0) {
uint32_t kpos = hash_to_key[pos];
uint32_t kpos_next = hash_to_key[next_pos];
SWAP(key_to_hash[kpos], key_to_hash[kpos_next]);
@@ -279,7 +277,7 @@ public:
SWAP(hash_to_key[next_pos], hash_to_key[pos]);
pos = next_pos;
next_pos = fastmod(pos + 1, capacity_inv, capacity);
next_pos = (pos + 1) % capacity;
}
hashes[pos] = EMPTY_HASH;
@@ -446,13 +444,6 @@ public:
capacity_index = MIN_CAPACITY_INDEX;
}
HashSet(std::initializer_list<TKey> p_init) {
reserve(p_init.size());
for (const TKey &E : p_init) {
insert(E);
}
}
void reset() {
clear();
@@ -482,3 +473,5 @@ public:
};
} // namespace godot
#endif // GODOT_HASH_SET_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_HASHFUNCS_HPP
#define GODOT_HASHFUNCS_HPP
// Needed for fastmod.
#if defined(_MSC_VER)
@@ -66,11 +67,10 @@ namespace godot {
static _FORCE_INLINE_ uint32_t hash_djb2(const char *p_cstr) {
const unsigned char *chr = (const unsigned char *)p_cstr;
uint32_t hash = 5381;
uint32_t c = *chr++;
uint32_t c;
while (c) {
while ((c = *chr++)) {
hash = ((hash << 5) + hash) ^ c; /* hash * 33 ^ c */
c = *chr++;
}
return hash;
@@ -108,16 +108,6 @@ static _FORCE_INLINE_ uint32_t hash_one_uint64(const uint64_t p_int) {
return uint32_t(v);
}
static _FORCE_INLINE_ uint64_t hash64_murmur3_64(uint64_t key, uint64_t seed) {
key ^= seed;
key ^= key >> 33;
key *= 0xff51afd7ed558ccd;
key ^= key >> 33;
key *= 0xc4ceb9fe1a85ec53;
key ^= key >> 33;
return key;
}
#define HASH_MURMUR3_SEED 0x7F07C65
// Murmurhash3 32-bit version.
// All MurmurHash versions are public domain software, and the author disclaims all copyright to their code.
@@ -238,7 +228,7 @@ static _FORCE_INLINE_ uint32_t hash_murmur3_buffer(const void *key, int length,
k1 = hash_rotl32(k1, 15);
k1 *= c2;
h1 ^= k1;
};
}
// Finalize with additional bit mixing.
h1 ^= length;
@@ -321,41 +311,40 @@ struct HashMapHasherDefault {
static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); }
static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(uint32_t(p_wchar)); }
static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); }
static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); }
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(p_wchar); }
static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(p_uchar); }
static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(p_uchar); }
static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); }
static _FORCE_INLINE_ uint32_t hash(const CharString &p_char_string) { return hash_djb2(p_char_string.get_data()); }
static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); }
static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); }
static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); }
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(uint64_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(p_int); }
static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_murmur3_one_float(p_float); }
static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_murmur3_one_double(p_double); }
static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return hash_fmix32(uint32_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return hash_fmix32(uint32_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return hash_fmix32(uint32_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return hash_fmix32(uint32_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return hash_fmix32(uint32_t(p_int)); }
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return hash_fmix32(p_int); }
static _FORCE_INLINE_ uint32_t hash(const Vector2i &p_vec) {
uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x));
h = hash_murmur3_one_32(uint32_t(p_vec.y), h);
uint32_t h = hash_murmur3_one_32(p_vec.x);
h = hash_murmur3_one_32(p_vec.y, h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Vector3i &p_vec) {
uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x));
h = hash_murmur3_one_32(uint32_t(p_vec.y), h);
h = hash_murmur3_one_32(uint32_t(p_vec.z), h);
uint32_t h = hash_murmur3_one_32(p_vec.x);
h = hash_murmur3_one_32(p_vec.y, h);
h = hash_murmur3_one_32(p_vec.z, h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Vector4i &p_vec) {
uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x));
h = hash_murmur3_one_32(uint32_t(p_vec.y), h);
h = hash_murmur3_one_32(uint32_t(p_vec.z), h);
h = hash_murmur3_one_32(uint32_t(p_vec.w), h);
uint32_t h = hash_murmur3_one_32(p_vec.x);
h = hash_murmur3_one_32(p_vec.y, h);
h = hash_murmur3_one_32(p_vec.z, h);
h = hash_murmur3_one_32(p_vec.w, h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) {
@@ -377,10 +366,10 @@ struct HashMapHasherDefault {
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) {
uint32_t h = hash_murmur3_one_32(uint32_t(p_rect.position.x));
h = hash_murmur3_one_32(uint32_t(p_rect.position.y), h);
h = hash_murmur3_one_32(uint32_t(p_rect.size.x), h);
h = hash_murmur3_one_32(uint32_t(p_rect.size.y), h);
uint32_t h = hash_murmur3_one_32(p_rect.position.x);
h = hash_murmur3_one_32(p_rect.position.y, h);
h = hash_murmur3_one_32(p_rect.size.x, h);
h = hash_murmur3_one_32(p_rect.size.y, h);
return hash_fmix32(h);
}
static _FORCE_INLINE_ uint32_t hash(const Rect2 &p_rect) {
@@ -401,19 +390,6 @@ struct HashMapHasherDefault {
}
};
struct HashHasher {
static _FORCE_INLINE_ uint32_t hash(const int32_t hash) { return hash; }
static _FORCE_INLINE_ uint32_t hash(const uint32_t hash) { return hash; }
static _FORCE_INLINE_ uint64_t hash(const int64_t hash) { return hash; }
static _FORCE_INLINE_ uint64_t hash(const uint64_t hash) { return hash; }
};
// TODO: Fold this into HashMapHasherDefault once C++20 concepts are allowed
template <typename T>
struct HashableHasher {
static _FORCE_INLINE_ uint32_t hash(const T &hashable) { return hashable.hash(); }
};
template <typename T>
struct HashMapComparatorDefault {
static bool compare(const T &p_lhs, const T &p_rhs) {
@@ -435,13 +411,6 @@ struct HashMapComparatorDefault<double> {
}
};
template <>
struct HashMapComparatorDefault<Color> {
static bool compare(const Color &p_lhs, const Color &p_rhs) {
return ((p_lhs.r == p_rhs.r) || (Math::is_nan(p_lhs.r) && Math::is_nan(p_rhs.r))) && ((p_lhs.g == p_rhs.g) || (Math::is_nan(p_lhs.g) && Math::is_nan(p_rhs.g))) && ((p_lhs.b == p_rhs.b) || (Math::is_nan(p_lhs.b) && Math::is_nan(p_rhs.b))) && ((p_lhs.a == p_rhs.a) || (Math::is_nan(p_lhs.a) && Math::is_nan(p_rhs.a)));
}
};
template <>
struct HashMapComparatorDefault<Vector2> {
static bool compare(const Vector2 &p_lhs, const Vector2 &p_rhs) {
@@ -456,90 +425,9 @@ struct HashMapComparatorDefault<Vector3> {
}
};
template <>
struct HashMapComparatorDefault<Vector4> {
static bool compare(const Vector4 &p_lhs, const Vector4 &p_rhs) {
return ((p_lhs.x == p_rhs.x) || (Math::is_nan(p_lhs.x) && Math::is_nan(p_rhs.x))) && ((p_lhs.y == p_rhs.y) || (Math::is_nan(p_lhs.y) && Math::is_nan(p_rhs.y))) && ((p_lhs.z == p_rhs.z) || (Math::is_nan(p_lhs.z) && Math::is_nan(p_rhs.z))) && ((p_lhs.w == p_rhs.w) || (Math::is_nan(p_lhs.w) && Math::is_nan(p_rhs.w)));
}
};
template <>
struct HashMapComparatorDefault<Rect2> {
static bool compare(const Rect2 &p_lhs, const Rect2 &p_rhs) {
return HashMapComparatorDefault<Vector2>().compare(p_lhs.position, p_rhs.position) && HashMapComparatorDefault<Vector2>().compare(p_lhs.size, p_rhs.size);
}
};
template <>
struct HashMapComparatorDefault<AABB> {
static bool compare(const AABB &p_lhs, const AABB &p_rhs) {
return HashMapComparatorDefault<Vector3>().compare(p_lhs.position, p_rhs.position) && HashMapComparatorDefault<Vector3>().compare(p_lhs.size, p_rhs.size);
}
};
template <>
struct HashMapComparatorDefault<Plane> {
static bool compare(const Plane &p_lhs, const Plane &p_rhs) {
return HashMapComparatorDefault<Vector3>().compare(p_lhs.normal, p_rhs.normal) && ((p_lhs.d == p_rhs.d) || (Math::is_nan(p_lhs.d) && Math::is_nan(p_rhs.d)));
}
};
template <>
struct HashMapComparatorDefault<Transform2D> {
static bool compare(const Transform2D &p_lhs, const Transform2D &p_rhs) {
for (int i = 0; i < 3; ++i) {
if (!HashMapComparatorDefault<Vector2>().compare(p_lhs.columns[i], p_rhs.columns[i])) {
return false;
}
}
return true;
}
};
template <>
struct HashMapComparatorDefault<Basis> {
static bool compare(const Basis &p_lhs, const Basis &p_rhs) {
for (int i = 0; i < 3; ++i) {
if (!HashMapComparatorDefault<Vector3>().compare(p_lhs.rows[i], p_rhs.rows[i])) {
return false;
}
}
return true;
}
};
template <>
struct HashMapComparatorDefault<Transform3D> {
static bool compare(const Transform3D &p_lhs, const Transform3D &p_rhs) {
return HashMapComparatorDefault<Basis>().compare(p_lhs.basis, p_rhs.basis) && HashMapComparatorDefault<Vector3>().compare(p_lhs.origin, p_rhs.origin);
}
};
template <>
struct HashMapComparatorDefault<Projection> {
static bool compare(const Projection &p_lhs, const Projection &p_rhs) {
for (int i = 0; i < 4; ++i) {
if (!HashMapComparatorDefault<Vector4>().compare(p_lhs.columns[i], p_rhs.columns[i])) {
return false;
}
}
return true;
}
};
template <>
struct HashMapComparatorDefault<Quaternion> {
static bool compare(const Quaternion &p_lhs, const Quaternion &p_rhs) {
return ((p_lhs.x == p_rhs.x) || (Math::is_nan(p_lhs.x) && Math::is_nan(p_rhs.x))) && ((p_lhs.y == p_rhs.y) || (Math::is_nan(p_lhs.y) && Math::is_nan(p_rhs.y))) && ((p_lhs.z == p_rhs.z) || (Math::is_nan(p_lhs.z) && Math::is_nan(p_rhs.z))) && ((p_lhs.w == p_rhs.w) || (Math::is_nan(p_lhs.w) && Math::is_nan(p_rhs.w)));
}
};
constexpr uint32_t HASH_TABLE_SIZE_MAX = 29;
inline constexpr uint32_t hash_table_size_primes[HASH_TABLE_SIZE_MAX] = {
const uint32_t hash_table_size_primes[HASH_TABLE_SIZE_MAX] = {
5,
13,
23,
@@ -572,7 +460,7 @@ inline constexpr uint32_t hash_table_size_primes[HASH_TABLE_SIZE_MAX] = {
};
// Computed with elem_i = UINT64_C (0 x FFFFFFFF FFFFFFFF ) / d_i + 1, where d_i is the i-th element of the above array.
inline constexpr uint64_t hash_table_size_primes_inv[HASH_TABLE_SIZE_MAX] = {
const uint64_t hash_table_size_primes_inv[HASH_TABLE_SIZE_MAX] = {
3689348814741910324,
1418980313362273202,
802032351030850071,
@@ -634,3 +522,5 @@ static _FORCE_INLINE_ uint32_t fastmod(const uint32_t n, const uint64_t c, const
}
} // namespace godot
#endif // GODOT_HASHFUNCS_HPP

View File

@@ -28,14 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_LIST_HPP
#define GODOT_LIST_HPP
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/memory.hpp>
#include <godot_cpp/templates/sort_array.hpp>
#include <initializer_list>
/**
* Generic Templatized Linked List Implementation.
* The implementation differs from the STL one because
@@ -135,8 +134,6 @@ public:
data->erase(this);
}
void transfer_to_back(List<T, A> *p_dst_list);
_FORCE_INLINE_ Element() {}
};
@@ -227,7 +224,7 @@ private:
Element *last = nullptr;
int size_cache = 0;
bool erase(Element *p_I) {
bool erase(const Element *p_I) {
ERR_FAIL_NULL_V(p_I, false);
ERR_FAIL_COND_V(p_I->data != this, false);
@@ -247,7 +244,7 @@ private:
p_I->next_ptr->prev_ptr = p_I->prev_ptr;
}
memdelete_allocator<Element, A>(p_I);
memdelete_allocator<Element, A>(const_cast<Element *>(p_I));
size_cache--;
return true;
@@ -433,7 +430,7 @@ public:
/**
* erase an element in the list, by iterator pointing to it. Return true if it was found/erased.
*/
bool erase(Element *p_I) {
bool erase(const Element *p_I) {
if (_data && p_I) {
bool ret = _data->erase(p_I);
@@ -525,14 +522,10 @@ public:
it = it->next();
}
}
void operator=(List &&p_list) {
if (unlikely(this == &p_list)) {
return;
}
clear();
_data = p_list._data;
p_list._data = nullptr;
// Index operator, kept for compatibility.
_FORCE_INLINE_ T &operator[](int p_index) {
return get(p_index);
}
// Random access to elements, use with care,
@@ -550,6 +543,11 @@ public:
return I->get();
}
// Index operator, kept for compatibility.
_FORCE_INLINE_ const T &operator[](int p_index) const {
return get(p_index);
}
// Random access to elements, use with care,
// do not use for iteration.
const T &get(int p_index) const {
@@ -723,8 +721,8 @@ public:
template <typename C>
void sort_custom() {
//this version uses auxiliary memory for speed.
//if you don't want to use auxiliary memory, use the in_place version
// this version uses auxiliary memory for speed.
// if you don't want to use auxiliary memory, use the in_place version
int s = size();
if (s < 2) {
@@ -772,19 +770,9 @@ public:
it = it->next();
}
}
List(List &&p_list) {
_data = p_list._data;
p_list._data = nullptr;
}
List() {}
List(std::initializer_list<T> p_init) {
for (const T &E : p_init) {
push_back(E);
}
}
~List() {
clear();
if (_data) {
@@ -794,41 +782,6 @@ public:
}
};
template <typename T, typename A>
void List<T, A>::Element::transfer_to_back(List<T, A> *p_dst_list) {
// Detach from current.
if (data->first == this) {
data->first = data->first->next_ptr;
}
if (data->last == this) {
data->last = data->last->prev_ptr;
}
if (prev_ptr) {
prev_ptr->next_ptr = next_ptr;
}
if (next_ptr) {
next_ptr->prev_ptr = prev_ptr;
}
data->size_cache--;
// Attach to the back of the new one.
if (!p_dst_list->_data) {
p_dst_list->_data = memnew_allocator(_Data, A);
p_dst_list->_data->first = this;
p_dst_list->_data->last = nullptr;
p_dst_list->_data->size_cache = 0;
prev_ptr = nullptr;
} else {
p_dst_list->_data->last->next_ptr = this;
prev_ptr = p_dst_list->_data->last;
}
p_dst_list->_data->last = this;
next_ptr = nullptr;
data = p_dst_list->_data;
p_dst_list->_data->size_cache++;
}
} // namespace godot
#endif // GODOT_LIST_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_LOCAL_VECTOR_HPP
#define GODOT_LOCAL_VECTOR_HPP
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/memory.hpp>
@@ -58,18 +59,21 @@ public:
return data;
}
// Must take a copy instead of a reference (see GH-31736).
_FORCE_INLINE_ void push_back(T p_elem) {
if (unlikely(count == capacity)) {
capacity = tight ? (capacity + 1) : MAX((U)1, capacity << 1);
if (capacity == 0) {
capacity = 1;
} else {
capacity <<= 1;
}
data = (T *)memrealloc(data, capacity * sizeof(T));
CRASH_COND_MSG(!data, "Out of memory");
}
if constexpr (!std::is_trivially_constructible_v<T> && !force_trivial) {
if constexpr (!std::is_trivially_constructible<T>::value && !force_trivial) {
memnew_placement(&data[count++], T(p_elem));
} else {
data[count++] = std::move(p_elem);
data[count++] = p_elem;
}
}
@@ -77,49 +81,31 @@ public:
ERR_FAIL_UNSIGNED_INDEX(p_index, count);
count--;
for (U i = p_index; i < count; i++) {
data[i] = std::move(data[i + 1]);
data[i] = data[i + 1];
}
if constexpr (!std::is_trivially_destructible_v<T> && !force_trivial) {
if constexpr (!std::is_trivially_destructible<T>::value && !force_trivial) {
data[count].~T();
}
}
/// Removes the item copying the last value into the position of the one to
/// remove. It's generally faster than `remove_at`.
/// remove. It's generally faster than `remove`.
void remove_at_unordered(U p_index) {
ERR_FAIL_INDEX(p_index, count);
count--;
if (count > p_index) {
data[p_index] = std::move(data[count]);
data[p_index] = data[count];
}
if constexpr (!std::is_trivially_destructible_v<T> && !force_trivial) {
if constexpr (!std::is_trivially_destructible<T>::value && !force_trivial) {
data[count].~T();
}
}
_FORCE_INLINE_ bool erase(const T &p_val) {
void erase(const T &p_val) {
int64_t idx = find(p_val);
if (idx >= 0) {
remove_at(idx);
return true;
}
return false;
}
U erase_multiple_unordered(const T &p_val) {
U from = 0;
U occurrences = 0;
while (true) {
int64_t idx = find(p_val, from);
if (idx == -1) {
break;
}
remove_at_unordered(idx);
from = idx;
occurrences++;
}
return occurrences;
}
void invert() {
@@ -151,7 +137,7 @@ public:
_FORCE_INLINE_ U size() const { return count; }
void resize(U p_size) {
if (p_size < count) {
if constexpr (!std::is_trivially_destructible_v<T> && !force_trivial) {
if constexpr (!std::is_trivially_destructible<T>::value && !force_trivial) {
for (U i = p_size; i < count; i++) {
data[i].~T();
}
@@ -159,11 +145,16 @@ public:
count = p_size;
} else if (p_size > count) {
if (unlikely(p_size > capacity)) {
capacity = tight ? p_size : nearest_power_of_2_templated(p_size);
if (capacity == 0) {
capacity = 1;
}
while (capacity < p_size) {
capacity <<= 1;
}
data = (T *)memrealloc(data, capacity * sizeof(T));
CRASH_COND_MSG(!data, "Out of memory");
}
if constexpr (!std::is_trivially_constructible_v<T> && !force_trivial) {
if constexpr (!std::is_trivially_constructible<T>::value && !force_trivial) {
for (U i = count; i < p_size; i++) {
memnew_placement(&data[i], T);
}
@@ -247,13 +238,13 @@ public:
void insert(U p_pos, T p_val) {
ERR_FAIL_UNSIGNED_INDEX(p_pos, count + 1);
if (p_pos == count) {
push_back(std::move(p_val));
push_back(p_val);
} else {
resize(count + 1);
for (U i = count - 1; i > p_pos; i--) {
data[i] = std::move(data[i - 1]);
data[i] = data[i - 1];
}
data[p_pos] = std::move(p_val);
data[p_pos] = p_val;
}
}
@@ -297,17 +288,9 @@ public:
operator Vector<T>() const {
Vector<T> ret;
ret.resize(count);
ret.resize(size());
T *w = ret.ptrw();
if (w) {
if constexpr (std::is_trivially_copyable_v<T>) {
memcpy(w, data, sizeof(T) * count);
} else {
for (U i = 0; i < count; i++) {
w[i] = data[i];
}
}
}
memcpy(w, data, sizeof(T) * count);
return ret;
}
@@ -315,9 +298,7 @@ public:
Vector<uint8_t> ret;
ret.resize(count * sizeof(T));
uint8_t *w = ret.ptrw();
if (w) {
memcpy(w, data, sizeof(T) * count);
}
memcpy(w, data, sizeof(T) * count);
return ret;
}
@@ -334,16 +315,6 @@ public:
data[i] = p_from.data[i];
}
}
_FORCE_INLINE_ LocalVector(LocalVector &&p_from) {
data = p_from.data;
count = p_from.count;
capacity = p_from.capacity;
p_from.data = nullptr;
p_from.count = 0;
p_from.capacity = 0;
}
inline void operator=(const LocalVector &p_from) {
resize(p_from.size());
for (U i = 0; i < p_from.count; i++) {
@@ -356,26 +327,6 @@ public:
data[i] = p_from[i];
}
}
inline void operator=(LocalVector &&p_from) {
if (unlikely(this == &p_from)) {
return;
}
reset();
data = p_from.data;
count = p_from.count;
capacity = p_from.capacity;
p_from.data = nullptr;
p_from.count = 0;
p_from.capacity = 0;
}
inline void operator=(Vector<T> &&p_from) {
resize(p_from.size());
for (U i = 0; i < count; i++) {
data[i] = std::move(p_from[i]);
}
}
_FORCE_INLINE_ ~LocalVector() {
if (data) {
@@ -388,3 +339,5 @@ template <typename T, typename U = uint32_t, bool force_trivial = false>
using TightLocalVector = LocalVector<T, U, force_trivial, true>;
} // namespace godot
#endif // GODOT_LOCAL_VECTOR_HPP

View File

@@ -28,9 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include <godot_cpp/templates/hashfuncs.hpp>
#ifndef GODOT_PAIR_HPP
#define GODOT_PAIR_HPP
namespace godot {
@@ -70,15 +69,6 @@ struct PairSort {
}
};
template <typename F, typename S>
struct PairHash {
static uint32_t hash(const Pair<F, S> &P) {
uint64_t h1 = HashMapHasherDefault::hash(P.first);
uint64_t h2 = HashMapHasherDefault::hash(P.second);
return hash_one_uint64((h1 << 32) | h2);
}
};
template <typename K, typename V>
struct KeyValue {
const K key;
@@ -113,3 +103,5 @@ struct KeyValueSort {
};
} // namespace godot
#endif // GODOT_PAIR_HPP

View File

@@ -28,14 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_RB_MAP_HPP
#define GODOT_RB_MAP_HPP
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/memory.hpp>
#include <godot_cpp/templates/pair.hpp>
#include <initializer_list>
namespace godot {
// based on the very nice implementation of rb-trees by:
@@ -99,8 +98,6 @@ public:
typedef KeyValue<K, V> ValueType;
struct Iterator {
friend class RBMap<K, V, C, A>;
_FORCE_INLINE_ KeyValue<K, V> &operator*() const {
return E->key_value();
}
@@ -114,16 +111,11 @@ public:
return *this;
}
_FORCE_INLINE_ bool operator==(const Iterator &p_it) const { return E == p_it.E; }
_FORCE_INLINE_ bool operator!=(const Iterator &p_it) const { return E != p_it.E; }
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
explicit operator bool() const {
return E != nullptr;
}
Iterator &operator=(const Iterator &p_it) {
E = p_it.E;
return *this;
}
Iterator(Element *p_E) { E = p_E; }
Iterator() {}
Iterator(const Iterator &p_it) { E = p_it.E; }
@@ -146,16 +138,11 @@ public:
return *this;
}
_FORCE_INLINE_ bool operator==(const ConstIterator &p_it) const { return E == p_it.E; }
_FORCE_INLINE_ bool operator!=(const ConstIterator &p_it) const { return E != p_it.E; }
_FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; }
_FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; }
explicit operator bool() const {
return E != nullptr;
}
ConstIterator &operator=(const ConstIterator &p_it) {
E = p_it.E;
return *this;
}
ConstIterator(const Element *p_E) { E = p_E; }
ConstIterator() {}
ConstIterator(const ConstIterator &p_it) { E = p_it.E; }
@@ -432,7 +419,7 @@ private:
new_node->right = _data._nil;
new_node->left = _data._nil;
//new_node->data=_data;
// new_node->data=_data;
if (new_parent == _data._root || less(p_key, new_parent->_data.key)) {
new_parent->left = new_node;
@@ -766,12 +753,6 @@ public:
_copy_from(p_map);
}
RBMap(std::initializer_list<KeyValue<K, V>> p_init) {
for (const KeyValue<K, V> &E : p_init) {
insert(E.key, E.value);
}
}
_FORCE_INLINE_ RBMap() {}
~RBMap() {
@@ -780,3 +761,5 @@ public:
};
} // namespace godot
#endif // GODOT_RB_MAP_HPP

View File

@@ -28,12 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_RB_SET_HPP
#define GODOT_RB_SET_HPP
#include <godot_cpp/core/memory.hpp>
#include <initializer_list>
// based on the very nice implementation of rb-trees by:
// https://web.archive.org/web/20120507164830/https://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
@@ -400,7 +399,7 @@ private:
new_node->right = _data._nil;
new_node->left = _data._nil;
new_node->value = p_value;
//new_node->data=_data;
// new_node->data=_data;
if (new_parent == _data._root || less(p_value, new_parent->value)) {
new_parent->left = new_node;
@@ -703,12 +702,6 @@ public:
_copy_from(p_set);
}
RBSet(std::initializer_list<T> p_init) {
for (const T &E : p_init) {
insert(E);
}
}
_FORCE_INLINE_ RBSet() {}
~RBSet() {
@@ -717,3 +710,5 @@ public:
};
} // namespace godot
#endif // GODOT_RB_SET_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_RID_OWNER_HPP
#define GODOT_RID_OWNER_HPP
#include <godot_cpp/core/memory.hpp>
#include <godot_cpp/godot.hpp>
@@ -460,3 +461,5 @@ public:
};
} // namespace godot
#endif // GODOT_RID_OWNER_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_SAFE_REFCOUNT_HPP
#define GODOT_SAFE_REFCOUNT_HPP
#if !defined(NO_THREADS)
@@ -51,7 +52,7 @@ namespace godot {
#define SAFE_NUMERIC_TYPE_PUN_GUARANTEES(m_type) \
static_assert(sizeof(SafeNumeric<m_type>) == sizeof(m_type)); \
static_assert(alignof(SafeNumeric<m_type>) == alignof(m_type)); \
static_assert(std::is_trivially_destructible_v<std::atomic<m_type>>);
static_assert(std::is_trivially_destructible<std::atomic<m_type>>::value);
#define SAFE_FLAG_TYPE_PUN_GUARANTEES \
static_assert(sizeof(SafeFlag) == sizeof(bool)); \
static_assert(alignof(SafeFlag) == alignof(bool));
@@ -102,17 +103,6 @@ public:
return value.fetch_sub(p_value, std::memory_order_acq_rel) - p_value;
}
_ALWAYS_INLINE_ T bit_or(T p_value) {
return value.fetch_or(p_value, std::memory_order_acq_rel);
}
_ALWAYS_INLINE_ T bit_and(T p_value) {
return value.fetch_and(p_value, std::memory_order_acq_rel);
}
_ALWAYS_INLINE_ T bit_xor(T p_value) {
return value.fetch_xor(p_value, std::memory_order_acq_rel);
}
// Returns the original value instead of the new one
_ALWAYS_INLINE_ T postsub(T p_value) {
return value.fetch_sub(p_value, std::memory_order_acq_rel);
@@ -124,8 +114,7 @@ public:
if (tmp >= p_value) {
return tmp; // already greater, or equal
}
if (value.compare_exchange_weak(tmp, p_value, std::memory_order_acq_rel)) {
if (value.compare_exchange_weak(tmp, p_value, std::memory_order_release)) {
return p_value;
}
}
@@ -137,7 +126,7 @@ public:
if (c == 0) {
return 0;
}
if (value.compare_exchange_weak(c, c + 1, std::memory_order_acq_rel)) {
if (value.compare_exchange_weak(c, c + 1, std::memory_order_release)) {
return c + 1;
}
}
@@ -178,16 +167,6 @@ public:
class SafeRefCount {
SafeNumeric<uint32_t> count;
#ifdef DEV_ENABLED
_ALWAYS_INLINE_ void _check_unref_safety() {
// This won't catch every misuse, but it's better than nothing.
CRASH_COND_MSG(count.get() == 0,
"Trying to unreference a SafeRefCount which is already zero is wrong and a symptom of it being misused.\n"
"Upon a SafeRefCount reaching zero any object whose lifetime is tied to it, as well as the ref count itself, must be destroyed.\n"
"Moreover, to guarantee that, no multiple threads should be racing to do the final unreferencing to zero.");
}
#endif
public:
_ALWAYS_INLINE_ bool ref() { // true on success
return count.conditional_increment() != 0;
@@ -198,16 +177,10 @@ public:
}
_ALWAYS_INLINE_ bool unref() { // true if must be disposed of
#ifdef DEV_ENABLED
_check_unref_safety();
#endif
return count.decrement() == 0;
}
_ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of
#ifdef DEV_ENABLED
_check_unref_safety();
#endif
return count.decrement();
}
@@ -220,6 +193,143 @@ public:
}
};
#else
template <typename T>
class SafeNumeric {
protected:
T value;
public:
_ALWAYS_INLINE_ void set(T p_value) {
value = p_value;
}
_ALWAYS_INLINE_ T get() const {
return value;
}
_ALWAYS_INLINE_ T increment() {
return ++value;
}
_ALWAYS_INLINE_ T postincrement() {
return value++;
}
_ALWAYS_INLINE_ T decrement() {
return --value;
}
_ALWAYS_INLINE_ T postdecrement() {
return value--;
}
_ALWAYS_INLINE_ T add(T p_value) {
return value += p_value;
}
_ALWAYS_INLINE_ T postadd(T p_value) {
T old = value;
value += p_value;
return old;
}
_ALWAYS_INLINE_ T sub(T p_value) {
return value -= p_value;
}
_ALWAYS_INLINE_ T postsub(T p_value) {
T old = value;
value -= p_value;
return old;
}
_ALWAYS_INLINE_ T exchange_if_greater(T p_value) {
if (value < p_value) {
value = p_value;
}
return value;
}
_ALWAYS_INLINE_ T conditional_increment() {
if (value == 0) {
return 0;
} else {
return ++value;
}
}
_ALWAYS_INLINE_ explicit SafeNumeric<T>(T p_value = static_cast<T>(0)) :
value(p_value) {
}
};
class SafeFlag {
protected:
bool flag;
public:
_ALWAYS_INLINE_ bool is_set() const {
return flag;
}
_ALWAYS_INLINE_ void set() {
flag = true;
}
_ALWAYS_INLINE_ void clear() {
flag = false;
}
_ALWAYS_INLINE_ void set_to(bool p_value) {
flag = p_value;
}
_ALWAYS_INLINE_ explicit SafeFlag(bool p_value = false) :
flag(p_value) {}
};
class SafeRefCount {
uint32_t count = 0;
public:
_ALWAYS_INLINE_ bool ref() { // true on success
if (count != 0) {
++count;
return true;
} else {
return false;
}
}
_ALWAYS_INLINE_ uint32_t refval() { // none-zero on success
if (count != 0) {
return ++count;
} else {
return 0;
}
}
_ALWAYS_INLINE_ bool unref() { // true if must be disposed of
return --count == 0;
}
_ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of
return --count;
}
_ALWAYS_INLINE_ uint32_t get() const {
return count;
}
_ALWAYS_INLINE_ void init(uint32_t p_value = 1) {
count = p_value;
}
};
#endif
} // namespace godot
#endif // !defined(NO_THREADS)
#endif // GODOT_SAFE_REFCOUNT_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_SEARCH_ARRAY_HPP
#define GODOT_SEARCH_ARRAY_HPP
#include <godot_cpp/templates/sort_array.hpp>
@@ -39,12 +40,12 @@ class SearchArray {
public:
Comparator compare;
inline int64_t bisect(const T *p_array, int64_t p_len, const T &p_value, bool p_before) const {
int64_t lo = 0;
int64_t hi = p_len;
inline int bisect(const T *p_array, int p_len, const T &p_value, bool p_before) const {
int lo = 0;
int hi = p_len;
if (p_before) {
while (lo < hi) {
const int64_t mid = (lo + hi) / 2;
const int mid = (lo + hi) / 2;
if (compare(p_array[mid], p_value)) {
lo = mid + 1;
} else {
@@ -53,7 +54,7 @@ public:
}
} else {
while (lo < hi) {
const int64_t mid = (lo + hi) / 2;
const int mid = (lo + hi) / 2;
if (compare(p_value, p_array[mid])) {
hi = mid;
} else {
@@ -66,3 +67,5 @@ public:
};
} // namespace godot
#endif // GODOT_SEARCH_ARRAY_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_SELF_LIST_HPP
#define GODOT_SELF_LIST_HPP
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/core/error_macros.hpp>
@@ -100,74 +101,11 @@ public:
p_elem->_root = nullptr;
}
void clear() {
while (_first) {
remove(_first);
}
}
void sort() {
sort_custom<Comparator<T>>();
}
template <typename C>
void sort_custom() {
if (_first == _last) {
return;
}
SelfList<T> *from = _first;
SelfList<T> *current = from;
SelfList<T> *to = from;
while (current) {
SelfList<T> *next = current->_next;
if (from != current) {
current->_prev = nullptr;
current->_next = from;
SelfList<T> *find = from;
C less;
while (find && less(*find->_self, *current->_self)) {
current->_prev = find;
current->_next = find->_next;
find = find->_next;
}
if (current->_prev) {
current->_prev->_next = current;
} else {
from = current;
}
if (current->_next) {
current->_next->_prev = current;
} else {
to = current;
}
} else {
current->_prev = nullptr;
current->_next = nullptr;
}
current = next;
}
_first = from;
_last = to;
}
_FORCE_INLINE_ SelfList<T> *first() { return _first; }
_FORCE_INLINE_ const SelfList<T> *first() const { return _first; }
// Forbid copying, which has broken behavior.
void operator=(const List &) = delete;
_FORCE_INLINE_ List() {}
_FORCE_INLINE_ ~List() {
// A self list must be empty on destruction.
DEV_ASSERT(_first == nullptr);
}
_FORCE_INLINE_ ~List() { ERR_FAIL_COND(_first != nullptr); }
};
private:
@@ -189,9 +127,6 @@ public:
_FORCE_INLINE_ const SelfList<T> *prev() const { return _prev; }
_FORCE_INLINE_ T *self() const { return _self; }
// Forbid copying, which has broken behavior.
void operator=(const SelfList<T> &) = delete;
_FORCE_INLINE_ SelfList(T *p_self) {
_self = p_self;
}
@@ -204,3 +139,5 @@ public:
};
} // namespace godot
#endif // GODOT_SELF_LIST_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_SORT_ARRAY_HPP
#define GODOT_SORT_ARRAY_HPP
#include <godot_cpp/core/error_macros.hpp>
@@ -78,8 +79,8 @@ public:
}
}
inline int64_t bitlog(int64_t n) const {
int64_t k;
inline int bitlog(int n) const {
int k;
for (k = 0; n != 1; n >>= 1) {
++k;
}
@@ -88,8 +89,8 @@ public:
/* Heap / Heapsort functions */
inline void push_heap(int64_t p_first, int64_t p_hole_idx, int64_t p_top_index, T p_value, T *p_array) const {
int64_t parent = (p_hole_idx - 1) / 2;
inline void push_heap(int p_first, int p_hole_idx, int p_top_index, T p_value, T *p_array) const {
int parent = (p_hole_idx - 1) / 2;
while (p_hole_idx > p_top_index && compare(p_array[p_first + parent], p_value)) {
p_array[p_first + p_hole_idx] = p_array[p_first + parent];
p_hole_idx = parent;
@@ -98,17 +99,17 @@ public:
p_array[p_first + p_hole_idx] = p_value;
}
inline void pop_heap(int64_t p_first, int64_t p_last, int64_t p_result, T p_value, T *p_array) const {
inline void pop_heap(int p_first, int p_last, int p_result, T p_value, T *p_array) const {
p_array[p_result] = p_array[p_first];
adjust_heap(p_first, 0, p_last - p_first, p_value, p_array);
}
inline void pop_heap(int64_t p_first, int64_t p_last, T *p_array) const {
inline void pop_heap(int p_first, int p_last, T *p_array) const {
pop_heap(p_first, p_last - 1, p_last - 1, p_array[p_last - 1], p_array);
}
inline void adjust_heap(int64_t p_first, int64_t p_hole_idx, int64_t p_len, T p_value, T *p_array) const {
int64_t top_index = p_hole_idx;
int64_t second_child = 2 * p_hole_idx + 2;
inline void adjust_heap(int p_first, int p_hole_idx, int p_len, T p_value, T *p_array) const {
int top_index = p_hole_idx;
int second_child = 2 * p_hole_idx + 2;
while (second_child < p_len) {
if (compare(p_array[p_first + second_child], p_array[p_first + (second_child - 1)])) {
@@ -127,18 +128,18 @@ public:
push_heap(p_first, p_hole_idx, top_index, p_value, p_array);
}
inline void sort_heap(int64_t p_first, int64_t p_last, T *p_array) const {
inline void sort_heap(int p_first, int p_last, T *p_array) const {
while (p_last - p_first > 1) {
pop_heap(p_first, p_last--, p_array);
}
}
inline void make_heap(int64_t p_first, int64_t p_last, T *p_array) const {
inline void make_heap(int p_first, int p_last, T *p_array) const {
if (p_last - p_first < 2) {
return;
}
int64_t len = p_last - p_first;
int64_t parent = (len - 2) / 2;
int len = p_last - p_first;
int parent = (len - 2) / 2;
while (true) {
adjust_heap(p_first, parent, len, p_array[p_first + parent], p_array);
@@ -149,9 +150,9 @@ public:
}
}
inline void partial_sort(int64_t p_first, int64_t p_last, int64_t p_middle, T *p_array) const {
inline void partial_sort(int p_first, int p_last, int p_middle, T *p_array) const {
make_heap(p_first, p_middle, p_array);
for (int64_t i = p_middle; i < p_last; i++) {
for (int i = p_middle; i < p_last; i++) {
if (compare(p_array[i], p_array[p_first])) {
pop_heap(p_first, p_middle, i, p_array[i], p_array);
}
@@ -159,29 +160,29 @@ public:
sort_heap(p_first, p_middle, p_array);
}
inline void partial_select(int64_t p_first, int64_t p_last, int64_t p_middle, T *p_array) const {
inline void partial_select(int p_first, int p_last, int p_middle, T *p_array) const {
make_heap(p_first, p_middle, p_array);
for (int64_t i = p_middle; i < p_last; i++) {
for (int i = p_middle; i < p_last; i++) {
if (compare(p_array[i], p_array[p_first])) {
pop_heap(p_first, p_middle, i, p_array[i], p_array);
}
}
}
inline int64_t partitioner(int64_t p_first, int64_t p_last, T p_pivot, T *p_array) const {
const int64_t unmodified_first = p_first;
const int64_t unmodified_last = p_last;
inline int partitioner(int p_first, int p_last, T p_pivot, T *p_array) const {
const int unmodified_first = p_first;
const int unmodified_last = p_last;
while (true) {
while (compare(p_array[p_first], p_pivot)) {
if constexpr (Validate) {
if (Validate) {
ERR_BAD_COMPARE(p_first == unmodified_last - 1);
}
p_first++;
}
p_last--;
while (compare(p_pivot, p_array[p_last])) {
if constexpr (Validate) {
if (Validate) {
ERR_BAD_COMPARE(p_last == unmodified_first);
}
p_last--;
@@ -196,7 +197,7 @@ public:
}
}
inline void introsort(int64_t p_first, int64_t p_last, T *p_array, int64_t p_max_depth) const {
inline void introsort(int p_first, int p_last, T *p_array, int p_max_depth) const {
while (p_last - p_first > INTROSORT_THRESHOLD) {
if (p_max_depth == 0) {
partial_sort(p_first, p_last, p_last, p_array);
@@ -205,7 +206,7 @@ public:
p_max_depth--;
int64_t cut = partitioner(
int cut = partitioner(
p_first,
p_last,
median_of_3(
@@ -219,7 +220,7 @@ public:
}
}
inline void introselect(int64_t p_first, int64_t p_nth, int64_t p_last, T *p_array, int64_t p_max_depth) const {
inline void introselect(int p_first, int p_nth, int p_last, T *p_array, int p_max_depth) const {
while (p_last - p_first > 3) {
if (p_max_depth == 0) {
partial_select(p_first, p_nth + 1, p_last, p_array);
@@ -229,7 +230,7 @@ public:
p_max_depth--;
int64_t cut = partitioner(
int cut = partitioner(
p_first,
p_last,
median_of_3(
@@ -248,10 +249,10 @@ public:
insertion_sort(p_first, p_last, p_array);
}
inline void unguarded_linear_insert(int64_t p_last, T p_value, T *p_array) const {
int64_t next = p_last - 1;
inline void unguarded_linear_insert(int p_last, T p_value, T *p_array) const {
int next = p_last - 1;
while (compare(p_value, p_array[next])) {
if constexpr (Validate) {
if (Validate) {
ERR_BAD_COMPARE(next == 0);
}
p_array[p_last] = p_array[next];
@@ -261,10 +262,10 @@ public:
p_array[p_last] = p_value;
}
inline void linear_insert(int64_t p_first, int64_t p_last, T *p_array) const {
inline void linear_insert(int p_first, int p_last, T *p_array) const {
T val = p_array[p_last];
if (compare(val, p_array[p_first])) {
for (int64_t i = p_last; i > p_first; i--) {
for (int i = p_last; i > p_first; i--) {
p_array[i] = p_array[i - 1];
}
@@ -274,22 +275,22 @@ public:
}
}
inline void insertion_sort(int64_t p_first, int64_t p_last, T *p_array) const {
inline void insertion_sort(int p_first, int p_last, T *p_array) const {
if (p_first == p_last) {
return;
}
for (int64_t i = p_first + 1; i != p_last; i++) {
for (int i = p_first + 1; i != p_last; i++) {
linear_insert(p_first, i, p_array);
}
}
inline void unguarded_insertion_sort(int64_t p_first, int64_t p_last, T *p_array) const {
for (int64_t i = p_first; i != p_last; i++) {
inline void unguarded_insertion_sort(int p_first, int p_last, T *p_array) const {
for (int i = p_first; i != p_last; i++) {
unguarded_linear_insert(i, p_array[i], p_array);
}
}
inline void final_insertion_sort(int64_t p_first, int64_t p_last, T *p_array) const {
inline void final_insertion_sort(int p_first, int p_last, T *p_array) const {
if (p_last - p_first > INTROSORT_THRESHOLD) {
insertion_sort(p_first, p_first + INTROSORT_THRESHOLD, p_array);
unguarded_insertion_sort(p_first + INTROSORT_THRESHOLD, p_last, p_array);
@@ -298,18 +299,18 @@ public:
}
}
inline void sort_range(int64_t p_first, int64_t p_last, T *p_array) const {
inline void sort_range(int p_first, int p_last, T *p_array) const {
if (p_first != p_last) {
introsort(p_first, p_last, p_array, bitlog(p_last - p_first) * 2);
final_insertion_sort(p_first, p_last, p_array);
}
}
inline void sort(T *p_array, int64_t p_len) const {
inline void sort(T *p_array, int p_len) const {
sort_range(0, p_len, p_array);
}
inline void nth_element(int64_t p_first, int64_t p_last, int64_t p_nth, T *p_array) const {
inline void nth_element(int p_first, int p_last, int p_nth, T *p_array) const {
if (p_first == p_last || p_nth == p_last) {
return;
}
@@ -318,3 +319,5 @@ public:
};
} // namespace godot
#endif // GODOT_SORT_ARRAY_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_SPIN_LOCK_HPP
#define GODOT_SPIN_LOCK_HPP
#include <atomic>
@@ -49,3 +50,5 @@ public:
};
} // namespace godot
#endif // GODOT_SPIN_LOCK_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_THREAD_WORK_POOL_HPP
#define GODOT_THREAD_WORK_POOL_HPP
#include <godot_cpp/classes/os.hpp>
#include <godot_cpp/classes/semaphore.hpp>
@@ -200,3 +201,5 @@ public:
};
} // namespace godot
#endif // GODOT_THREAD_WORK_POOL_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_VECTOR_HPP
#define GODOT_VECTOR_HPP
/**
* @class Vector
@@ -68,7 +69,6 @@ private:
CowData<T> _cowdata;
public:
// Must take a copy instead of a reference (see GH-31736).
bool push_back(T p_elem);
_FORCE_INLINE_ bool append(const T &p_elem) { return push_back(p_elem); } //alias
void fill(T p_elem);
@@ -97,13 +97,11 @@ public:
Error resize(Size p_size) { return _cowdata.resize(p_size); }
Error resize_zeroed(Size p_size) { return _cowdata.template resize<true>(p_size); }
_FORCE_INLINE_ const T &operator[](Size p_index) const { return _cowdata.get(p_index); }
// Must take a copy instead of a reference (see GH-31736).
Error insert(Size p_pos, T p_val) { return _cowdata.insert(p_pos, p_val); }
Size find(const T &p_val, Size p_from = 0) const { return _cowdata.find(p_val, p_from); }
Size rfind(const T &p_val, Size p_from = -1) const { return _cowdata.rfind(p_val, p_from); }
Size count(const T &p_val) const { return _cowdata.count(p_val); }
// Must take a copy instead of a reference (see GH-31736).
void append_array(Vector<T> p_other);
_FORCE_INLINE_ bool has(const T &p_val) const { return find(p_val) != -1; }
@@ -148,19 +146,17 @@ public:
insert(i, p_val);
}
void operator=(const Vector &p_from) { _cowdata._ref(p_from._cowdata); }
void operator=(Vector &&p_from) { _cowdata = std::move(p_from._cowdata); }
inline void operator=(const Vector &p_from) {
_cowdata._ref(p_from._cowdata);
}
Vector<uint8_t> to_byte_array() const {
Vector<uint8_t> ret;
if (is_empty()) {
return ret;
}
size_t alloc_size = size() * sizeof(T);
ret.resize(alloc_size);
if (alloc_size) {
memcpy(ret.ptrw(), ptr(), alloc_size);
}
ret.resize(size() * sizeof(T));
memcpy(ret.ptrw(), ptr(), sizeof(T) * size());
return ret;
}
@@ -283,11 +279,16 @@ public:
}
_FORCE_INLINE_ Vector() {}
_FORCE_INLINE_ Vector(std::initializer_list<T> p_init) :
_cowdata(p_init) {}
_FORCE_INLINE_ Vector(std::initializer_list<T> p_init) {
Error err = _cowdata.resize(p_init.size());
ERR_FAIL_COND(err);
Size i = 0;
for (const T &element : p_init) {
_cowdata.set(i++, element);
}
}
_FORCE_INLINE_ Vector(const Vector &p_from) { _cowdata._ref(p_from._cowdata); }
_FORCE_INLINE_ Vector(Vector &&p_from) :
_cowdata(std::move(p_from._cowdata)) {}
_FORCE_INLINE_ ~Vector() {}
};
@@ -331,3 +332,5 @@ void Vector<T>::fill(T p_elem) {
}
} // namespace godot
#endif // GODOT_VECTOR_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_VMAP_HPP
#define GODOT_VMAP_HPP
#include <godot_cpp/templates/cowdata.hpp>
@@ -72,16 +73,16 @@ private:
middle = (low + high) / 2;
if (p_val < a[middle].key) {
high = middle - 1; //search low end of array
high = middle - 1; // search low end of array
} else if (a[middle].key < p_val) {
low = middle + 1; //search high end of array
low = middle + 1; // search high end of array
} else {
r_exact = true;
return middle;
}
}
//return the position where this would be inserted
// return the position where this would be inserted
if (a[middle].key < p_val) {
middle++;
}
@@ -102,9 +103,9 @@ private:
middle = (low + high) / 2;
if (p_val < a[middle].key) {
high = middle - 1; //search low end of array
high = middle - 1; // search low end of array
} else if (a[middle].key < p_val) {
low = middle + 1; //search high end of array
low = middle + 1; // search high end of array
} else {
return middle;
}
@@ -142,9 +143,6 @@ public:
}
int find_nearest(const T &p_val) const {
if (_cowdata.is_empty()) {
return -1;
}
bool exact;
return _find(p_val, exact);
}
@@ -194,8 +192,6 @@ public:
}
_FORCE_INLINE_ VMap() {}
_FORCE_INLINE_ VMap(std::initializer_list<T> p_init) :
_cowdata(p_init) {}
_FORCE_INLINE_ VMap(const VMap &p_from) { _cowdata._ref(p_from._cowdata); }
inline void operator=(const VMap &p_from) {
@@ -204,3 +200,5 @@ public:
};
} // namespace godot
#endif // GODOT_VMAP_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_VSET_HPP
#define GODOT_VSET_HPP
#include <godot_cpp/templates/vector.hpp>
@@ -59,16 +60,16 @@ class VSet {
middle = (low + high) / 2;
if (p_val < a[middle]) {
high = middle - 1; //search low end of array
high = middle - 1; // search low end of array
} else if (a[middle] < p_val) {
low = middle + 1; //search high end of array
low = middle + 1; // search high end of array
} else {
r_exact = true;
return middle;
}
}
//return the position where this would be inserted
// return the position where this would be inserted
if (a[middle] < p_val) {
middle++;
}
@@ -89,9 +90,9 @@ class VSet {
middle = (low + high) / 2;
if (p_val < a[middle]) {
high = middle - 1; //search low end of array
high = middle - 1; // search low end of array
} else if (a[middle] < p_val) {
low = middle + 1; //search high end of array
low = middle + 1; // search high end of array
} else {
return middle;
}
@@ -137,10 +138,8 @@ public:
inline const T &operator[](int p_index) const {
return _data[p_index];
}
_FORCE_INLINE_ VSet() {}
_FORCE_INLINE_ VSet(std::initializer_list<T> p_init) :
_data(p_init) {}
};
} // namespace godot
#endif // GODOT_VSET_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_AABB_HPP
#define GODOT_AABB_HPP
#include <godot_cpp/variant/plane.hpp>
#include <godot_cpp/variant/vector3.hpp>
@@ -72,21 +73,16 @@ struct [[nodiscard]] AABB {
AABB merge(const AABB &p_with) const;
void merge_with(const AABB &p_aabb); ///merge with another AABB
AABB intersection(const AABB &p_aabb) const; ///get box where two intersect, empty if no intersection occurs
_FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t p_t0, real_t p_t1) const;
bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_intersection_point = nullptr, Vector3 *r_normal = nullptr) const;
bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir) const {
bool inside;
return find_intersects_ray(p_from, p_dir, inside);
}
bool find_intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, bool &r_inside, Vector3 *r_intersection_point = nullptr, Vector3 *r_normal = nullptr) const;
bool intersects_segment(const Vector3 &p_from, const Vector3 &p_to, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const;
bool intersects_ray(const Vector3 &p_from, const Vector3 &p_dir, Vector3 *r_clip = nullptr, Vector3 *r_normal = nullptr) const;
_FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const;
_FORCE_INLINE_ bool intersects_convex_shape(const Plane *p_planes, int p_plane_count, const Vector3 *p_points, int p_point_count) const;
_FORCE_INLINE_ bool inside_convex_shape(const Plane *p_planes, int p_plane_count) const;
bool intersects_plane(const Plane &p_plane) const;
_FORCE_INLINE_ bool has_point(const Vector3 &p_point) const;
_FORCE_INLINE_ Vector3 get_support(const Vector3 &p_direction) const;
_FORCE_INLINE_ Vector3 get_support(const Vector3 &p_normal) const;
Vector3 get_longest_axis() const;
int get_longest_axis_index() const;
@@ -213,18 +209,15 @@ inline bool AABB::encloses(const AABB &p_aabb) const {
(src_max.z >= dst_max.z));
}
Vector3 AABB::get_support(const Vector3 &p_direction) const {
Vector3 support = position;
if (p_direction.x > 0.0f) {
support.x += size.x;
}
if (p_direction.y > 0.0f) {
support.y += size.y;
}
if (p_direction.z > 0.0f) {
support.z += size.z;
}
return support;
Vector3 AABB::get_support(const Vector3 &p_normal) const {
Vector3 half_extents = size * 0.5f;
Vector3 ofs = position + half_extents;
return Vector3(
(p_normal.x > 0) ? half_extents.x : -half_extents.x,
(p_normal.y > 0) ? half_extents.y : -half_extents.y,
(p_normal.z > 0) ? half_extents.z : -half_extents.z) +
ofs;
}
Vector3 AABB::get_endpoint(int p_point) const {
@@ -410,7 +403,7 @@ inline real_t AABB::get_shortest_axis_size() const {
return max_size;
}
bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t p_t0, real_t p_t1) const {
bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real_t t0, real_t t1) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || size.z < 0)) {
ERR_PRINT("AABB size is negative, this is not supported. Use AABB.abs() to get an AABB with a positive size.");
@@ -461,7 +454,7 @@ bool AABB::smits_intersect_ray(const Vector3 &p_from, const Vector3 &p_dir, real
if (tzmax < tmax) {
tmax = tzmax;
}
return ((tmin < p_t1) && (tmax > p_t0));
return ((tmin < t1) && (tmax > t0));
}
void AABB::grow_by(real_t p_amount) {
@@ -498,3 +491,5 @@ AABB AABB::quantized(real_t p_unit) const {
}
} // namespace godot
#endif // GODOT_AABB_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_ARRAY_HELPERS_HPP
#define GODOT_ARRAY_HELPERS_HPP
namespace godot {
namespace helpers {
@@ -50,3 +51,5 @@ T append_all(T appendable) {
}
} // namespace helpers
} // namespace godot
#endif // GODOT_ARRAY_HELPERS_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_BASIS_HPP
#define GODOT_BASIS_HPP
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/variant/quaternion.hpp>
@@ -43,11 +44,11 @@ struct [[nodiscard]] Basis {
Vector3(0, 0, 1)
};
_FORCE_INLINE_ const Vector3 &operator[](int p_row) const {
return rows[p_row];
_FORCE_INLINE_ const Vector3 &operator[](int axis) const {
return rows[axis];
}
_FORCE_INLINE_ Vector3 &operator[](int p_row) {
return rows[p_row];
_FORCE_INLINE_ Vector3 &operator[](int axis) {
return rows[axis];
}
void invert();
@@ -58,19 +59,21 @@ struct [[nodiscard]] Basis {
_FORCE_INLINE_ real_t determinant() const;
void from_z(const Vector3 &p_z);
void rotate(const Vector3 &p_axis, real_t p_angle);
Basis rotated(const Vector3 &p_axis, real_t p_angle) const;
void rotate_local(const Vector3 &p_axis, real_t p_angle);
Basis rotated_local(const Vector3 &p_axis, real_t p_angle) const;
void rotate(const Vector3 &p_euler, EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ);
Basis rotated(const Vector3 &p_euler, EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ) const;
void rotate(const Vector3 &p_euler, EulerOrder p_order = EULER_ORDER_YXZ);
Basis rotated(const Vector3 &p_euler, EulerOrder p_order = EULER_ORDER_YXZ) const;
void rotate(const Quaternion &p_quaternion);
Basis rotated(const Quaternion &p_quaternion) const;
Vector3 get_euler_normalized(EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ) const;
Vector3 get_euler_normalized(EulerOrder p_order = EULER_ORDER_YXZ) const;
void get_rotation_axis_angle(Vector3 &p_axis, real_t &p_angle) const;
void get_rotation_axis_angle_local(Vector3 &p_axis, real_t &p_angle) const;
Quaternion get_rotation_quaternion() const;
@@ -79,9 +82,9 @@ struct [[nodiscard]] Basis {
Vector3 rotref_posscale_decomposition(Basis &rotref) const;
Vector3 get_euler(EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ) const;
void set_euler(const Vector3 &p_euler, EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ);
static Basis from_euler(const Vector3 &p_euler, EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ) {
Vector3 get_euler(EulerOrder p_order = EULER_ORDER_YXZ) const;
void set_euler(const Vector3 &p_euler, EulerOrder p_order = EULER_ORDER_YXZ);
static Basis from_euler(const Vector3 &p_euler, EulerOrder p_order = EULER_ORDER_YXZ) {
Basis b;
b.set_euler(p_euler, p_order);
return b;
@@ -101,25 +104,27 @@ struct [[nodiscard]] Basis {
void scale_orthogonal(const Vector3 &p_scale);
Basis scaled_orthogonal(const Vector3 &p_scale) const;
real_t get_uniform_scale() const;
void make_scale_uniform();
float get_uniform_scale() const;
Vector3 get_scale() const;
Vector3 get_scale_abs() const;
Vector3 get_scale_global() const;
Vector3 get_scale_local() const;
void set_axis_angle_scale(const Vector3 &p_axis, real_t p_angle, const Vector3 &p_scale);
void set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale, EulerOrder p_order = EulerOrder::EULER_ORDER_YXZ);
void set_euler_scale(const Vector3 &p_euler, const Vector3 &p_scale, EulerOrder p_order = EULER_ORDER_YXZ);
void set_quaternion_scale(const Quaternion &p_quaternion, const Vector3 &p_scale);
// transposed dot products
_FORCE_INLINE_ real_t tdotx(const Vector3 &p_v) const {
return rows[0][0] * p_v[0] + rows[1][0] * p_v[1] + rows[2][0] * p_v[2];
_FORCE_INLINE_ real_t tdotx(const Vector3 &v) const {
return rows[0][0] * v[0] + rows[1][0] * v[1] + rows[2][0] * v[2];
}
_FORCE_INLINE_ real_t tdoty(const Vector3 &p_v) const {
return rows[0][1] * p_v[0] + rows[1][1] * p_v[1] + rows[2][1] * p_v[2];
_FORCE_INLINE_ real_t tdoty(const Vector3 &v) const {
return rows[0][1] * v[0] + rows[1][1] * v[1] + rows[2][1] * v[2];
}
_FORCE_INLINE_ real_t tdotz(const Vector3 &p_v) const {
return rows[0][2] * p_v[0] + rows[1][2] * p_v[1] + rows[2][2] * p_v[2];
_FORCE_INLINE_ real_t tdotz(const Vector3 &v) const {
return rows[0][2] * v[0] + rows[1][2] * v[1] + rows[2][2] * v[2];
}
bool is_equal_approx(const Basis &p_basis) const;
@@ -136,35 +141,31 @@ struct [[nodiscard]] Basis {
_FORCE_INLINE_ Basis operator+(const Basis &p_matrix) const;
_FORCE_INLINE_ void operator-=(const Basis &p_matrix);
_FORCE_INLINE_ Basis operator-(const Basis &p_matrix) const;
_FORCE_INLINE_ void operator*=(real_t p_val);
_FORCE_INLINE_ Basis operator*(real_t p_val) const;
_FORCE_INLINE_ void operator/=(real_t p_val);
_FORCE_INLINE_ Basis operator/(real_t p_val) const;
_FORCE_INLINE_ void operator*=(const real_t p_val);
_FORCE_INLINE_ Basis operator*(const real_t p_val) const;
bool is_orthogonal() const;
bool is_orthonormal() const;
bool is_conformal() const;
bool is_diagonal() const;
bool is_rotation() const;
Basis lerp(const Basis &p_to, real_t p_weight) const;
Basis slerp(const Basis &p_to, real_t p_weight) const;
Basis lerp(const Basis &p_to, const real_t &p_weight) const;
Basis slerp(const Basis &p_to, const real_t &p_weight) const;
void rotate_sh(real_t *p_values);
operator String() const;
/* create / set */
_FORCE_INLINE_ void set(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz) {
rows[0][0] = p_xx;
rows[0][1] = p_xy;
rows[0][2] = p_xz;
rows[1][0] = p_yx;
rows[1][1] = p_yy;
rows[1][2] = p_yz;
rows[2][0] = p_zx;
rows[2][1] = p_zy;
rows[2][2] = p_zz;
_FORCE_INLINE_ void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) {
rows[0][0] = xx;
rows[0][1] = xy;
rows[0][2] = xz;
rows[1][0] = yx;
rows[1][1] = yy;
rows[1][2] = yz;
rows[2][0] = zx;
rows[2][1] = zy;
rows[2][2] = zz;
}
_FORCE_INLINE_ void set_columns(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z) {
set_column(0, p_x);
@@ -194,20 +195,20 @@ struct [[nodiscard]] Basis {
rows[2].zero();
}
_FORCE_INLINE_ Basis transpose_xform(const Basis &p_m) const {
_FORCE_INLINE_ Basis transpose_xform(const Basis &m) const {
return Basis(
rows[0].x * p_m[0].x + rows[1].x * p_m[1].x + rows[2].x * p_m[2].x,
rows[0].x * p_m[0].y + rows[1].x * p_m[1].y + rows[2].x * p_m[2].y,
rows[0].x * p_m[0].z + rows[1].x * p_m[1].z + rows[2].x * p_m[2].z,
rows[0].y * p_m[0].x + rows[1].y * p_m[1].x + rows[2].y * p_m[2].x,
rows[0].y * p_m[0].y + rows[1].y * p_m[1].y + rows[2].y * p_m[2].y,
rows[0].y * p_m[0].z + rows[1].y * p_m[1].z + rows[2].y * p_m[2].z,
rows[0].z * p_m[0].x + rows[1].z * p_m[1].x + rows[2].z * p_m[2].x,
rows[0].z * p_m[0].y + rows[1].z * p_m[1].y + rows[2].z * p_m[2].y,
rows[0].z * p_m[0].z + rows[1].z * p_m[1].z + rows[2].z * p_m[2].z);
rows[0].x * m[0].x + rows[1].x * m[1].x + rows[2].x * m[2].x,
rows[0].x * m[0].y + rows[1].x * m[1].y + rows[2].x * m[2].y,
rows[0].x * m[0].z + rows[1].x * m[1].z + rows[2].x * m[2].z,
rows[0].y * m[0].x + rows[1].y * m[1].x + rows[2].y * m[2].x,
rows[0].y * m[0].y + rows[1].y * m[1].y + rows[2].y * m[2].y,
rows[0].y * m[0].z + rows[1].y * m[1].z + rows[2].y * m[2].z,
rows[0].z * m[0].x + rows[1].z * m[1].x + rows[2].z * m[2].x,
rows[0].z * m[0].y + rows[1].z * m[1].y + rows[2].z * m[2].y,
rows[0].z * m[0].z + rows[1].z * m[1].z + rows[2].z * m[2].z);
}
Basis(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz) {
set(p_xx, p_xy, p_xz, p_yx, p_yy, p_yz, p_zx, p_zy, p_zz);
Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) {
set(xx, xy, xz, yx, yy, yz, zx, zy, zz);
}
void orthonormalize();
@@ -281,30 +282,18 @@ _FORCE_INLINE_ Basis Basis::operator-(const Basis &p_matrix) const {
return ret;
}
_FORCE_INLINE_ void Basis::operator*=(real_t p_val) {
_FORCE_INLINE_ void Basis::operator*=(const real_t p_val) {
rows[0] *= p_val;
rows[1] *= p_val;
rows[2] *= p_val;
}
_FORCE_INLINE_ Basis Basis::operator*(real_t p_val) const {
_FORCE_INLINE_ Basis Basis::operator*(const real_t p_val) const {
Basis ret(*this);
ret *= p_val;
return ret;
}
_FORCE_INLINE_ void Basis::operator/=(real_t p_val) {
rows[0] /= p_val;
rows[1] /= p_val;
rows[2] /= p_val;
}
_FORCE_INLINE_ Basis Basis::operator/(real_t p_val) const {
Basis ret(*this);
ret /= p_val;
return ret;
}
Vector3 Basis::xform(const Vector3 &p_vector) const {
return Vector3(
rows[0].dot(p_vector),
@@ -326,3 +315,5 @@ real_t Basis::determinant() const {
}
} // namespace godot
#endif // GODOT_BASIS_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_CALLABLE_CUSTOM_HPP
#define GODOT_CALLABLE_CUSTOM_HPP
#include <godot_cpp/core/object_id.hpp>
#include <godot_cpp/variant/string_name.hpp>
@@ -60,3 +61,5 @@ public:
};
} // namespace godot
#endif // GODOT_CALLABLE_CUSTOM_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_CALLABLE_METHOD_POINTER_HPP
#define GODOT_CALLABLE_METHOD_POINTER_HPP
#include <godot_cpp/core/binder_common.hpp>
#include <godot_cpp/variant/variant.hpp>
@@ -104,7 +105,8 @@ template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
R (T::*method)(P...);
R(T::*method)
(P...);
} data;
static_assert(sizeof(Data) % 4 == 0);
@@ -145,7 +147,8 @@ template <typename T, typename R, typename... P>
class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
struct Data {
T *instance;
R (T::*method)(P...) const;
R(T::*method)
(P...) const;
} data;
static_assert(sizeof(Data) % 4 == 0);
@@ -225,7 +228,8 @@ Callable create_custom_callable_static_function_pointer(void (*p_method)(P...))
template <typename R, typename... P>
class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase {
struct Data {
R (*method)(P...);
R(*method)
(P...);
} data;
static_assert(sizeof(Data) % 4 == 0);
@@ -265,3 +269,5 @@ Callable create_custom_callable_static_function_pointer(R (*p_method)(P...)) {
#define callable_mp_static(M) ::godot::create_custom_callable_static_function_pointer(M)
} // namespace godot
#endif // GODOT_CALLABLE_METHOD_POINTER_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_CHAR_STRING_HPP
#define GODOT_CHAR_STRING_HPP
#include <godot_cpp/templates/cowdata.hpp>
@@ -113,7 +114,7 @@ public:
CharStringT<T> &operator+=(T p_char);
int64_t length() const { return size() ? size() - 1 : 0; }
const T *get_data() const;
operator const T *() const { return get_data(); }
operator const T *() const { return get_data(); };
protected:
void copy_from(const T *p_cstr);
@@ -137,3 +138,5 @@ typedef CharStringT<char32_t> Char32String;
typedef CharStringT<wchar_t> CharWideString;
} // namespace godot
#endif // GODOT_CHAR_STRING_HPP

View File

@@ -28,107 +28,63 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_CHAR_UTILS_HPP
#define GODOT_CHAR_UTILS_HPP
#include "char_range.inc.hpp"
namespace godot {
#define BSEARCH_CHAR_RANGE(m_array) \
int low = 0; \
int high = sizeof(m_array) / sizeof(m_array[0]) - 1; \
int middle = (low + high) / 2; \
\
while (low <= high) { \
if (p_char < m_array[middle].start) { \
high = middle - 1; \
} else if (p_char > m_array[middle].end) { \
low = middle + 1; \
} else { \
return true; \
} \
\
middle = (low + high) / 2; \
} \
\
return false
constexpr bool is_unicode_identifier_start(char32_t p_char) {
BSEARCH_CHAR_RANGE(xid_start);
static _FORCE_INLINE_ bool is_ascii_upper_case(char32_t c) {
return (c >= 'A' && c <= 'Z');
}
constexpr bool is_unicode_identifier_continue(char32_t p_char) {
BSEARCH_CHAR_RANGE(xid_continue);
static _FORCE_INLINE_ bool is_ascii_lower_case(char32_t c) {
return (c >= 'a' && c <= 'z');
}
constexpr bool is_unicode_upper_case(char32_t p_char) {
BSEARCH_CHAR_RANGE(uppercase_letter);
static _FORCE_INLINE_ bool is_digit(char32_t c) {
return (c >= '0' && c <= '9');
}
constexpr bool is_unicode_lower_case(char32_t p_char) {
BSEARCH_CHAR_RANGE(lowercase_letter);
static _FORCE_INLINE_ bool is_hex_digit(char32_t c) {
return (is_digit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
}
constexpr bool is_unicode_letter(char32_t p_char) {
BSEARCH_CHAR_RANGE(unicode_letter);
static _FORCE_INLINE_ bool is_binary_digit(char32_t c) {
return (c == '0' || c == '1');
}
#undef BSEARCH_CHAR_RANGE
constexpr bool is_ascii_upper_case(char32_t p_char) {
return (p_char >= 'A' && p_char <= 'Z');
static _FORCE_INLINE_ bool is_ascii_char(char32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
constexpr bool is_ascii_lower_case(char32_t p_char) {
return (p_char >= 'a' && p_char <= 'z');
static _FORCE_INLINE_ bool is_ascii_alphanumeric_char(char32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
}
constexpr bool is_digit(char32_t p_char) {
return (p_char >= '0' && p_char <= '9');
static _FORCE_INLINE_ bool is_ascii_identifier_char(char32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_';
}
constexpr bool is_hex_digit(char32_t p_char) {
return (is_digit(p_char) || (p_char >= 'a' && p_char <= 'f') || (p_char >= 'A' && p_char <= 'F'));
static _FORCE_INLINE_ bool is_symbol(char32_t c) {
return c != '_' && ((c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~') || c == '\t' || c == ' ');
}
constexpr bool is_binary_digit(char32_t p_char) {
return (p_char == '0' || p_char == '1');
}
constexpr bool is_ascii_alphabet_char(char32_t p_char) {
return (p_char >= 'a' && p_char <= 'z') || (p_char >= 'A' && p_char <= 'Z');
}
constexpr bool is_ascii_alphanumeric_char(char32_t p_char) {
return (p_char >= 'a' && p_char <= 'z') || (p_char >= 'A' && p_char <= 'Z') || (p_char >= '0' && p_char <= '9');
}
constexpr bool is_ascii_identifier_char(char32_t p_char) {
return (p_char >= 'a' && p_char <= 'z') || (p_char >= 'A' && p_char <= 'Z') || (p_char >= '0' && p_char <= '9') || p_char == '_';
}
constexpr bool is_symbol(char32_t p_char) {
return p_char != '_' && ((p_char >= '!' && p_char <= '/') || (p_char >= ':' && p_char <= '@') || (p_char >= '[' && p_char <= '`') || (p_char >= '{' && p_char <= '~') || p_char == '\t' || p_char == ' ');
}
constexpr bool is_control(char32_t p_char) {
static _FORCE_INLINE_ bool is_control(char32_t p_char) {
return (p_char <= 0x001f) || (p_char >= 0x007f && p_char <= 0x009f);
}
constexpr bool is_whitespace(char32_t p_char) {
return (p_char == ' ') || (p_char == 0x00a0) || (p_char == 0x1680) || (p_char >= 0x2000 && p_char <= 0x200b) || (p_char == 0x202f) || (p_char == 0x205f) || (p_char == 0x3000) || (p_char == 0x2028) || (p_char == 0x2029) || (p_char >= 0x0009 && p_char <= 0x000d) || (p_char == 0x0085);
static _FORCE_INLINE_ bool is_whitespace(char32_t p_char) {
return (p_char == ' ') || (p_char == 0x00a0) || (p_char == 0x1680) || (p_char >= 0x2000 && p_char <= 0x200a) || (p_char == 0x202f) || (p_char == 0x205f) || (p_char == 0x3000) || (p_char == 0x2028) || (p_char == 0x2029) || (p_char >= 0x0009 && p_char <= 0x000d) || (p_char == 0x0085);
}
constexpr bool is_linebreak(char32_t p_char) {
static _FORCE_INLINE_ bool is_linebreak(char32_t p_char) {
return (p_char >= 0x000a && p_char <= 0x000d) || (p_char == 0x0085) || (p_char == 0x2028) || (p_char == 0x2029);
}
constexpr bool is_punct(char32_t p_char) {
static _FORCE_INLINE_ bool is_punct(char32_t p_char) {
return (p_char >= ' ' && p_char <= '/') || (p_char >= ':' && p_char <= '@') || (p_char >= '[' && p_char <= '^') || (p_char == '`') || (p_char >= '{' && p_char <= '~') || (p_char >= 0x2000 && p_char <= 0x206f) || (p_char >= 0x3000 && p_char <= 0x303f);
}
constexpr bool is_underscore(char32_t p_char) {
static _FORCE_INLINE_ bool is_underscore(char32_t p_char) {
return (p_char == '_');
}
} // namespace godot
#endif // GODOT_CHAR_UTILS_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_COLOR_HPP
#define GODOT_COLOR_HPP
#include <godot_cpp/core/math.hpp>
@@ -102,10 +103,12 @@ struct [[nodiscard]] Color {
_FORCE_INLINE_ Color lerp(const Color &p_to, float p_weight) const {
Color res = *this;
res.r = Math::lerp(res.r, p_to.r, p_weight);
res.g = Math::lerp(res.g, p_to.g, p_weight);
res.b = Math::lerp(res.b, p_to.b, p_weight);
res.a = Math::lerp(res.a, p_to.a, p_weight);
res.r += (p_weight * (p_to.r - r));
res.g += (p_weight * (p_to.g - g));
res.b += (p_weight * (p_to.b - b));
res.a += (p_weight * (p_to.a - a));
return res;
}
@@ -126,46 +129,33 @@ struct [[nodiscard]] Color {
}
_FORCE_INLINE_ uint32_t to_rgbe9995() const {
// https://github.com/microsoft/DirectX-Graphics-Samples/blob/v10.0.19041.0/MiniEngine/Core/Color.cpp
static const float kMaxVal = float(0x1FF << 7);
static const float kMinVal = float(1.f / (1 << 16));
const float pow2to9 = 512.0f;
const float B = 15.0f;
const float N = 9.0f;
// Clamp RGB to [0, 1.FF*2^16]
const float _r = CLAMP(r, 0.0f, kMaxVal);
const float _g = CLAMP(g, 0.0f, kMaxVal);
const float _b = CLAMP(b, 0.0f, kMaxVal);
float sharedexp = 65408.000f; // Result of: ((pow2to9 - 1.0f) / pow2to9) * powf(2.0f, 31.0f - 15.0f)
// Compute the maximum channel, no less than 1.0*2^-15
const float MaxChannel = MAX(MAX(_r, _g), MAX(_b, kMinVal));
float cRed = MAX(0.0f, MIN(sharedexp, r));
float cGreen = MAX(0.0f, MIN(sharedexp, g));
float cBlue = MAX(0.0f, MIN(sharedexp, b));
// Take the exponent of the maximum channel (rounding up the 9th bit) and
// add 15 to it. When added to the channels, it causes the implicit '1.0'
// bit and the first 8 mantissa bits to be shifted down to the low 9 bits
// of the mantissa, rounding the truncated bits.
union {
float f;
uint32_t i;
} R, G, B, E;
float cMax = MAX(cRed, MAX(cGreen, cBlue));
E.f = MaxChannel;
E.i += 0x07804000; // Add 15 to the exponent and 0x4000 to the mantissa
E.i &= 0x7F800000; // Zero the mantissa
float expp = MAX(-B - 1.0f, floor(Math::log(cMax) / (real_t)Math_LN2)) + 1.0f + B;
// This shifts the 9-bit values we need into the lowest bits, rounding as
// needed. Note that if the channel has a smaller exponent than the max
// channel, it will shift even more. This is intentional.
R.f = _r + E.f;
G.f = _g + E.f;
B.f = _b + E.f;
float sMax = (float)floor((cMax / Math::pow(2.0f, expp - B - N)) + 0.5f);
// Convert the Bias to the correct exponent in the upper 5 bits.
E.i <<= 4;
E.i += 0x10000000;
float exps = expp + 1.0f;
// Combine the fields. RGB floats have unwanted data in the upper 9
// bits. Only red needs to mask them off because green and blue shift
// it out to the left.
return E.i | (B.i << 18U) | (G.i << 9U) | (R.i & 511U);
if (0.0f <= sMax && sMax < pow2to9) {
exps = expp;
}
float sRed = Math::floor((cRed / pow(2.0f, exps - B - N)) + 0.5f);
float sGreen = Math::floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
float sBlue = Math::floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
return (uint32_t(Math::fast_ftoi(sRed)) & 0x1FF) | ((uint32_t(Math::fast_ftoi(sGreen)) & 0x1FF) << 9) | ((uint32_t(Math::fast_ftoi(sBlue)) & 0x1FF) << 18) | ((uint32_t(Math::fast_ftoi(exps)) & 0x1F) << 27);
}
_FORCE_INLINE_ Color blend(const Color &p_over) const {
@@ -184,16 +174,16 @@ struct [[nodiscard]] Color {
_FORCE_INLINE_ Color srgb_to_linear() const {
return Color(
r < 0.04045f ? r * (1.0f / 12.92f) : Math::pow(float((r + 0.055) * (1.0 / (1.0 + 0.055))), 2.4f),
g < 0.04045f ? g * (1.0f / 12.92f) : Math::pow(float((g + 0.055) * (1.0 / (1.0 + 0.055))), 2.4f),
b < 0.04045f ? b * (1.0f / 12.92f) : Math::pow(float((b + 0.055) * (1.0 / (1.0 + 0.055))), 2.4f),
r < 0.04045f ? r * (1.0f / 12.92f) : Math::pow((r + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f),
g < 0.04045f ? g * (1.0f / 12.92f) : Math::pow((g + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f),
b < 0.04045f ? b * (1.0f / 12.92f) : Math::pow((b + 0.055f) * (float)(1.0 / (1.0 + 0.055)), 2.4f),
a);
}
_FORCE_INLINE_ Color linear_to_srgb() const {
return Color(
r < 0.0031308f ? 12.92f * r : (1.0 + 0.055) * Math::pow(r, 1.0f / 2.4f) - 0.055,
g < 0.0031308f ? 12.92f * g : (1.0 + 0.055) * Math::pow(g, 1.0f / 2.4f) - 0.055,
b < 0.0031308f ? 12.92f * b : (1.0 + 0.055) * Math::pow(b, 1.0f / 2.4f) - 0.055, a);
r < 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * Math::pow(r, 1.0f / 2.4f) - 0.055f,
g < 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * Math::pow(g, 1.0f / 2.4f) - 0.055f,
b < 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * Math::pow(b, 1.0f / 2.4f) - 0.055f, a);
}
static Color hex(uint32_t p_hex);
@@ -209,7 +199,6 @@ struct [[nodiscard]] Color {
static Color from_string(const String &p_string, const Color &p_default);
static Color from_hsv(float p_h, float p_s, float p_v, float p_alpha = 1.0f);
static Color from_rgbe9995(uint32_t p_rgbe);
static Color from_rgba8(int64_t p_r8, int64_t p_g8, int64_t p_b8, int64_t p_a8 = 255);
_FORCE_INLINE_ bool operator<(const Color &p_color) const; // Used in set keys.
operator String() const;
@@ -296,3 +285,5 @@ _FORCE_INLINE_ Color operator*(float p_scalar, const Color &p_color) {
}
} // namespace godot
#endif // GODOT_COLOR_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_COLOR_NAMES_INC_HPP
#define GODOT_COLOR_NAMES_INC_HPP
namespace godot {
@@ -187,6 +188,9 @@ static NamedColor named_colors[] = {
{ "WHITE_SMOKE", Color::hex(0xF5F5F5FF) },
{ "YELLOW", Color::hex(0xFFFF00FF) },
{ "YELLOW_GREEN", Color::hex(0x9ACD32FF) },
{ nullptr, Color() },
};
} // namespace godot
#endif // GODOT_COLOR_NAMES_INC_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_PLANE_HPP
#define GODOT_PLANE_HPP
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/variant/vector3.hpp>
@@ -49,7 +50,7 @@ struct [[nodiscard]] Plane {
/* Plane-Point operations */
_FORCE_INLINE_ Vector3 get_center() const { return normal * d; }
_FORCE_INLINE_ Vector3 center() const { return normal * d; }
Vector3 get_any_perpendicular_normal() const;
_FORCE_INLINE_ bool is_point_over(const Vector3 &p_point) const; ///< Point is over plane
@@ -136,3 +137,5 @@ bool Plane::operator!=(const Plane &p_plane) const {
}
} // namespace godot
#endif // GODOT_PLANE_HPP

View File

@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_PROJECTION_HPP
#define GODOT_PROJECTION_HPP
#include <godot_cpp/core/math.hpp>
#include <godot_cpp/templates/vector.hpp>
#include <godot_cpp/variant/vector3.hpp>
#include <godot_cpp/variant/vector4.hpp>
@@ -56,21 +56,21 @@ struct [[nodiscard]] Projection {
Vector4 columns[4];
_FORCE_INLINE_ const Vector4 &operator[](int p_axis) const {
_FORCE_INLINE_ const Vector4 &operator[](const int p_axis) const {
DEV_ASSERT((unsigned int)p_axis < 4);
return columns[p_axis];
}
_FORCE_INLINE_ Vector4 &operator[](int p_axis) {
_FORCE_INLINE_ Vector4 &operator[](const int p_axis) {
DEV_ASSERT((unsigned int)p_axis < 4);
return columns[p_axis];
}
real_t determinant() const;
float determinant() const;
void set_identity();
void set_zero();
void set_light_bias();
void set_depth_correction(bool p_flip_y = true, bool p_reverse_z = true, bool p_remap_z = true);
void set_depth_correction(bool p_flip_y = true);
void set_light_atlas_rect(const Rect2 &p_rect);
void set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t p_z_near, real_t p_z_far, bool p_flip_fov = false);
@@ -107,7 +107,7 @@ struct [[nodiscard]] Projection {
real_t get_fov() const;
bool is_orthogonal() const;
Vector<Plane> get_projection_planes(const Transform3D &p_transform) const;
Array get_projection_planes(const Transform3D &p_transform) const;
bool get_endpoints(const Transform3D &p_transform, Vector3 *p_8points) const;
Vector2 get_viewport_half_extents() const;
@@ -149,7 +149,7 @@ struct [[nodiscard]] Projection {
return !(*this == p_cam);
}
real_t get_lod_multiplier() const;
float get_lod_multiplier() const;
Projection();
Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w);
@@ -168,3 +168,5 @@ Vector3 Projection::xform(const Vector3 &p_vec3) const {
}
} // namespace godot
#endif // GODOT_PROJECTION_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_QUATERNION_HPP
#define GODOT_QUATERNION_HPP
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/core/math.hpp>
@@ -142,24 +143,15 @@ struct [[nodiscard]] Quaternion {
}
Quaternion(const Vector3 &p_v0, const Vector3 &p_v1) { // Shortest arc.
#ifdef MATH_CHECKS
ERR_FAIL_COND_MSG(p_v0.is_zero_approx() || p_v1.is_zero_approx(), "The vectors must not be zero.");
#endif
constexpr real_t ALMOST_ONE = 1.0f - (real_t)CMP_EPSILON;
Vector3 n0 = p_v0.normalized();
Vector3 n1 = p_v1.normalized();
real_t d = n0.dot(n1);
if (Math::abs(d) > ALMOST_ONE) {
if (d >= 0) {
return; // Vectors are same.
}
Vector3 axis = n0.get_any_perpendicular();
x = axis.x;
y = axis.y;
z = axis.z;
Vector3 c = p_v0.cross(p_v1);
real_t d = p_v0.dot(p_v1);
if (d < -1.0f + (real_t)CMP_EPSILON) {
x = 0;
y = 1;
z = 0;
w = 0;
} else {
Vector3 c = n0.cross(n1);
real_t s = Math::sqrt((1.0f + d) * 2.0f);
real_t rs = 1.0f / s;
@@ -240,3 +232,5 @@ _FORCE_INLINE_ Quaternion operator*(real_t p_real, const Quaternion &p_quaternio
}
} // namespace godot
#endif // GODOT_QUATERNION_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_RECT2_HPP
#define GODOT_RECT2_HPP
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/variant/vector2.hpp>
@@ -52,7 +53,7 @@ struct [[nodiscard]] Rect2 {
_FORCE_INLINE_ Vector2 get_center() const { return position + (size * 0.5f); }
inline bool intersects(const Rect2 &p_rect, bool p_include_borders = false) const {
inline bool intersects(const Rect2 &p_rect, const bool p_include_borders = false) const {
#ifdef MATH_CHECKS
if (unlikely(size.x < 0 || size.y < 0 || p_rect.size.x < 0 || p_rect.size.y < 0)) {
ERR_PRINT("Rect2 size is negative, this is not supported. Use Rect2.abs() to get a Rect2 with a positive size.");
@@ -105,17 +106,17 @@ struct [[nodiscard]] Rect2 {
}
if (p_point.y < position.y) {
real_t d = position.y - p_point.y;
dist = inside ? d : MIN(dist, d);
dist = inside ? d : Math::min(dist, d);
inside = false;
}
if (p_point.x >= (position.x + size.x)) {
real_t d = p_point.x - (position.x + size.x);
dist = inside ? d : MIN(dist, d);
dist = inside ? d : Math::min(dist, d);
inside = false;
}
if (p_point.y >= (position.y + size.y)) {
real_t d = p_point.y - (position.y + size.y);
dist = inside ? d : MIN(dist, d);
dist = inside ? d : Math::min(dist, d);
inside = false;
}
@@ -145,7 +146,7 @@ struct [[nodiscard]] Rect2 {
return size.x > 0.0f && size.y > 0.0f;
}
// Returns the intersection between two Rect2s or an empty Rect2 if there is no intersection.
// Returns the intersection between two Rect2s or an empty Rect2 if there is no intersection
inline Rect2 intersection(const Rect2 &p_rect) const {
Rect2 new_rect = p_rect;
@@ -282,19 +283,13 @@ struct [[nodiscard]] Rect2 {
return Rect2(position + size.minf(0), size.abs());
}
_FORCE_INLINE_ Rect2 round() const {
return Rect2(position.round(), size.round());
}
Vector2 get_support(const Vector2 &p_direction) const {
Vector2 support = position;
if (p_direction.x > 0.0f) {
support.x += size.x;
}
if (p_direction.y > 0.0f) {
support.y += size.y;
}
return support;
Vector2 get_support(const Vector2 &p_normal) const {
Vector2 half_extents = size * 0.5f;
Vector2 ofs = position + half_extents;
return Vector2(
(p_normal.x > 0) ? -half_extents.x : half_extents.x,
(p_normal.y > 0) ? -half_extents.y : half_extents.y) +
ofs;
}
_FORCE_INLINE_ bool intersects_filled_polygon(const Vector2 *p_points, int p_point_count) const {
@@ -310,14 +305,14 @@ struct [[nodiscard]] Rect2 {
i_f = i;
Vector2 r = (b - a);
const real_t l = r.length();
float l = r.length();
if (l == 0.0f) {
continue;
}
// Check inside.
Vector2 tg = r.orthogonal();
const real_t s = tg.dot(center) - tg.dot(a);
float s = tg.dot(center) - tg.dot(a);
if (s < 0.0f) {
side_plus++;
} else {
@@ -333,8 +328,8 @@ struct [[nodiscard]] Rect2 {
Vector2 t13 = (position - a) * ir;
Vector2 t24 = (end - a) * ir;
const real_t tmin = MAX(MIN(t13.x, t24.x), MIN(t13.y, t24.y));
const real_t tmax = MIN(MAX(t13.x, t24.x), MAX(t13.y, t24.y));
float tmin = Math::max(Math::min(t13.x, t24.x), Math::min(t13.y, t24.y));
float tmax = Math::min(Math::max(t13.x, t24.x), Math::max(t13.y, t24.y));
// if tmax < 0, ray (line) is intersecting AABB, but the whole AABB is behind us
if (tmax < 0 || tmin > tmax || tmin >= l) {
@@ -374,3 +369,5 @@ struct [[nodiscard]] Rect2 {
};
} // namespace godot
#endif // GODOT_RECT2_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_RECT2I_HPP
#define GODOT_RECT2I_HPP
#include <godot_cpp/classes/global_constants.hpp>
#include <godot_cpp/variant/vector2i.hpp>
@@ -88,7 +89,7 @@ struct [[nodiscard]] Rect2i {
return size.x > 0 && size.y > 0;
}
// Returns the intersection between two Rect2is or an empty Rect2i if there is no intersection.
// Returns the intersection between two Rect2is or an empty Rect2i if there is no intersection
inline Rect2i intersection(const Rect2i &p_rect) const {
Rect2i new_rect = p_rect;
@@ -240,3 +241,5 @@ struct [[nodiscard]] Rect2i {
};
} // namespace godot
#endif // GODOT_RECT2I_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_TRANSFORM2D_HPP
#define GODOT_TRANSFORM2D_HPP
#include <godot_cpp/variant/packed_vector2_array.hpp>
#include <godot_cpp/variant/rect2.hpp>
@@ -39,24 +40,21 @@ namespace godot {
class String;
struct [[nodiscard]] Transform2D {
// WARNING: The basis of Transform2D is stored differently from Basis.
// In terms of columns array, the basis matrix looks like "on paper":
// Warning #1: basis of Transform2D is stored differently from Basis. In terms of columns array, the basis matrix looks like "on paper":
// M = (columns[0][0] columns[1][0])
// (columns[0][1] columns[1][1])
// This is such that the columns, which can be interpreted as basis vectors
// of the coordinate system "painted" on the object, can be accessed as columns[i].
// NOTE: This is the opposite of the indices in mathematical texts,
// meaning: $M_{12}$ in a math book corresponds to columns[1][0] here.
// This is such that the columns, which can be interpreted as basis vectors of the coordinate system "painted" on the object, can be accessed as columns[i].
// Note that this is the opposite of the indices in mathematical texts, meaning: $M_{12}$ in a math book corresponds to columns[1][0] here.
// This requires additional care when working with explicit indices.
// See https://en.wikipedia.org/wiki/Row-_and_column-major_order for further reading.
// WARNING: Be aware that unlike 3D code, 2D code uses a left-handed coordinate system:
// Y-axis points down, and angle is measure from +X to +Y in a clockwise-fashion.
// Warning #2: 2D be aware that unlike 3D code, 2D code uses a left-handed coordinate system: Y-axis points down,
// and angle is measure from +X to +Y in a clockwise-fashion.
Vector2 columns[3];
_FORCE_INLINE_ real_t tdotx(const Vector2 &p_v) const { return columns[0][0] * p_v.x + columns[1][0] * p_v.y; }
_FORCE_INLINE_ real_t tdoty(const Vector2 &p_v) const { return columns[0][1] * p_v.x + columns[1][1] * p_v.y; }
_FORCE_INLINE_ real_t tdotx(const Vector2 &v) const { return columns[0][0] * v.x + columns[1][0] * v.y; }
_FORCE_INLINE_ real_t tdoty(const Vector2 &v) const { return columns[0][1] * v.x + columns[1][1] * v.y; }
const Vector2 &operator[](int p_idx) const { return columns[p_idx]; }
Vector2 &operator[](int p_idx) { return columns[p_idx]; }
@@ -67,20 +65,20 @@ struct [[nodiscard]] Transform2D {
void affine_invert();
Transform2D affine_inverse() const;
void set_rotation(real_t p_rot);
void set_rotation(const real_t p_rot);
real_t get_rotation() const;
real_t get_skew() const;
void set_skew(real_t p_angle);
_FORCE_INLINE_ void set_rotation_and_scale(real_t p_rot, const Size2 &p_scale);
_FORCE_INLINE_ void set_rotation_scale_and_skew(real_t p_rot, const Size2 &p_scale, real_t p_skew);
void rotate(real_t p_angle);
void set_skew(const real_t p_angle);
_FORCE_INLINE_ void set_rotation_and_scale(const real_t p_rot, const Size2 &p_scale);
_FORCE_INLINE_ void set_rotation_scale_and_skew(const real_t p_rot, const Size2 &p_scale, const real_t p_skew);
void rotate(const real_t p_angle);
void scale(const Size2 &p_scale);
void scale_basis(const Size2 &p_scale);
void translate_local(real_t p_tx, real_t p_ty);
void translate_local(const real_t p_tx, const real_t p_ty);
void translate_local(const Vector2 &p_translation);
real_t determinant() const;
real_t basis_determinant() const;
Size2 get_scale() const;
void set_scale(const Size2 &p_scale);
@@ -88,18 +86,18 @@ struct [[nodiscard]] Transform2D {
_FORCE_INLINE_ const Vector2 &get_origin() const { return columns[2]; }
_FORCE_INLINE_ void set_origin(const Vector2 &p_origin) { columns[2] = p_origin; }
Transform2D basis_scaled(const Size2 &p_scale) const;
Transform2D scaled(const Size2 &p_scale) const;
Transform2D scaled_local(const Size2 &p_scale) const;
Transform2D translated(const Vector2 &p_offset) const;
Transform2D translated_local(const Vector2 &p_offset) const;
Transform2D rotated(real_t p_angle) const;
Transform2D rotated_local(real_t p_angle) const;
Transform2D rotated(const real_t p_angle) const;
Transform2D rotated_local(const real_t p_angle) const;
Transform2D untranslated() const;
void orthonormalize();
Transform2D orthonormalized() const;
bool is_conformal() const;
bool is_equal_approx(const Transform2D &p_transform) const;
bool is_finite() const;
@@ -110,12 +108,10 @@ struct [[nodiscard]] Transform2D {
void operator*=(const Transform2D &p_transform);
Transform2D operator*(const Transform2D &p_transform) const;
void operator*=(real_t p_val);
Transform2D operator*(real_t p_val) const;
void operator/=(real_t p_val);
Transform2D operator/(real_t p_val) const;
void operator*=(const real_t p_val);
Transform2D operator*(const real_t p_val) const;
Transform2D interpolate_with(const Transform2D &p_transform, real_t p_c) const;
Transform2D interpolate_with(const Transform2D &p_transform, const real_t p_c) const;
_FORCE_INLINE_ Vector2 basis_xform(const Vector2 &p_vec) const;
_FORCE_INLINE_ Vector2 basis_xform_inv(const Vector2 &p_vec) const;
@@ -128,13 +124,13 @@ struct [[nodiscard]] Transform2D {
operator String() const;
Transform2D(real_t p_xx, real_t p_xy, real_t p_yx, real_t p_yy, real_t p_ox, real_t p_oy) {
columns[0][0] = p_xx;
columns[0][1] = p_xy;
columns[1][0] = p_yx;
columns[1][1] = p_yy;
columns[2][0] = p_ox;
columns[2][1] = p_oy;
Transform2D(const real_t xx, const real_t xy, const real_t yx, const real_t yy, const real_t ox, const real_t oy) {
columns[0][0] = xx;
columns[0][1] = xy;
columns[1][0] = yx;
columns[1][1] = yy;
columns[2][0] = ox;
columns[2][1] = oy;
}
Transform2D(const Vector2 &p_x, const Vector2 &p_y, const Vector2 &p_origin) {
@@ -143,9 +139,9 @@ struct [[nodiscard]] Transform2D {
columns[2] = p_origin;
}
Transform2D(real_t p_rot, const Vector2 &p_pos);
Transform2D(const real_t p_rot, const Vector2 &p_pos);
Transform2D(real_t p_rot, const Size2 &p_scale, real_t p_skew, const Vector2 &p_pos);
Transform2D(const real_t p_rot, const Size2 &p_scale, const real_t p_skew, const Vector2 &p_pos);
Transform2D() {
columns[0][0] = 1.0;
@@ -193,14 +189,14 @@ Rect2 Transform2D::xform(const Rect2 &p_rect) const {
return new_rect;
}
void Transform2D::set_rotation_and_scale(real_t p_rot, const Size2 &p_scale) {
void Transform2D::set_rotation_and_scale(const real_t p_rot, const Size2 &p_scale) {
columns[0][0] = Math::cos(p_rot) * p_scale.x;
columns[1][1] = Math::cos(p_rot) * p_scale.y;
columns[1][0] = -Math::sin(p_rot) * p_scale.y;
columns[0][1] = Math::sin(p_rot) * p_scale.x;
}
void Transform2D::set_rotation_scale_and_skew(real_t p_rot, const Size2 &p_scale, real_t p_skew) {
void Transform2D::set_rotation_scale_and_skew(const real_t p_rot, const Size2 &p_scale, const real_t p_skew) {
columns[0][0] = Math::cos(p_rot) * p_scale.x;
columns[1][1] = Math::cos(p_rot + p_skew) * p_scale.y;
columns[1][0] = -Math::sin(p_rot + p_skew) * p_scale.y;
@@ -251,3 +247,5 @@ PackedVector2Array Transform2D::xform_inv(const PackedVector2Array &p_array) con
}
} // namespace godot
#endif // GODOT_TRANSFORM2D_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_TRANSFORM3D_HPP
#define GODOT_TRANSFORM3D_HPP
#include <godot_cpp/core/math.hpp>
#include <godot_cpp/variant/aabb.hpp>
@@ -54,8 +55,8 @@ struct [[nodiscard]] Transform3D {
void rotate(const Vector3 &p_axis, real_t p_angle);
void rotate_basis(const Vector3 &p_axis, real_t p_angle);
void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false);
Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0), bool p_use_model_front = false) const;
void set_look_at(const Vector3 &p_eye, const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0));
Transform3D looking_at(const Vector3 &p_target, const Vector3 &p_up = Vector3(0, 1, 0)) const;
void scale(const Vector3 &p_scale);
Transform3D scaled(const Vector3 &p_scale) const;
@@ -104,10 +105,8 @@ struct [[nodiscard]] Transform3D {
void operator*=(const Transform3D &p_transform);
Transform3D operator*(const Transform3D &p_transform) const;
void operator*=(real_t p_val);
Transform3D operator*(real_t p_val) const;
void operator/=(real_t p_val);
Transform3D operator/(real_t p_val) const;
void operator*=(const real_t p_val);
Transform3D operator*(const real_t p_val) const;
Transform3D interpolate_with(const Transform3D &p_transform, real_t p_c) const;
@@ -117,11 +116,11 @@ struct [[nodiscard]] Transform3D {
basis.xform(v));
}
void set(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_tx, real_t p_ty, real_t p_tz) {
basis.set(p_xx, p_xy, p_xz, p_yx, p_yy, p_yz, p_zx, p_zy, p_zz);
origin.x = p_tx;
origin.y = p_ty;
origin.z = p_tz;
void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t tx, real_t ty, real_t tz) {
basis.set(xx, xy, xz, yx, yy, yz, zx, zy, zz);
origin.x = tx;
origin.y = ty;
origin.z = tz;
}
operator String() const;
@@ -129,7 +128,7 @@ struct [[nodiscard]] Transform3D {
Transform3D() {}
Transform3D(const Basis &p_basis, const Vector3 &p_origin = Vector3());
Transform3D(const Vector3 &p_x, const Vector3 &p_y, const Vector3 &p_z, const Vector3 &p_origin);
Transform3D(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_ox, real_t p_oy, real_t p_oz);
Transform3D(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz, real_t ox, real_t oy, real_t oz);
};
_FORCE_INLINE_ Vector3 Transform3D::xform(const Vector3 &p_vector) const {
@@ -273,3 +272,5 @@ _FORCE_INLINE_ Plane Transform3D::xform_inv_fast(const Plane &p_plane, const Tra
}
} // namespace godot
#endif // GODOT_TRANSFORM3D_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_TYPED_ARRAY_HPP
#define GODOT_TYPED_ARRAY_HPP
#include <godot_cpp/variant/array.hpp>
#include <godot_cpp/variant/variant.hpp>
@@ -40,7 +41,7 @@ class TypedArray : public Array {
public:
_FORCE_INLINE_ void operator=(const Array &p_array) {
ERR_FAIL_COND_MSG(!is_same_typed(p_array), "Cannot assign an array with a different element type.");
Array::operator=(p_array);
_ref(p_array);
}
_FORCE_INLINE_ TypedArray(const Variant &p_variant) :
TypedArray(Array(p_variant)) {
@@ -48,13 +49,11 @@ public:
_FORCE_INLINE_ TypedArray(const Array &p_array) {
set_typed(Variant::OBJECT, T::get_class_static(), Variant());
if (is_same_typed(p_array)) {
Array::operator=(p_array);
_ref(p_array);
} else {
assign(p_array);
}
}
_FORCE_INLINE_ TypedArray(std::initializer_list<Variant> p_init) :
TypedArray(Array(p_init)) {}
_FORCE_INLINE_ TypedArray() {
set_typed(Variant::OBJECT, T::get_class_static(), Variant());
}
@@ -68,10 +67,7 @@ public:
public: \
_FORCE_INLINE_ void operator=(const Array &p_array) { \
ERR_FAIL_COND_MSG(!is_same_typed(p_array), "Cannot assign an array with a different element type."); \
Array::operator=(p_array); \
} \
_FORCE_INLINE_ TypedArray(std::initializer_list<Variant> p_init) : \
Array(Array(p_init), m_variant_type, StringName(), Variant()) { \
_ref(p_array); \
} \
_FORCE_INLINE_ TypedArray(const Variant &p_variant) : \
TypedArray(Array(p_variant)) { \
@@ -79,7 +75,7 @@ public:
_FORCE_INLINE_ TypedArray(const Array &p_array) { \
set_typed(m_variant_type, StringName(), Variant()); \
if (is_same_typed(p_array)) { \
Array::operator=(p_array); \
_ref(p_array); \
} else { \
assign(p_array); \
} \
@@ -142,3 +138,5 @@ MAKE_TYPED_ARRAY(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
#undef MAKE_TYPED_ARRAY
} // namespace godot
#endif // GODOT_TYPED_ARRAY_HPP

View File

@@ -1,465 +0,0 @@
/**************************************************************************/
/* typed_dictionary.hpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include <godot_cpp/core/type_info.hpp>
#include <godot_cpp/templates/pair.hpp>
#include <godot_cpp/variant/dictionary.hpp>
#include <godot_cpp/variant/variant.hpp>
namespace godot {
template <typename K, typename V>
class TypedDictionary : public Dictionary {
public:
_FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) {
ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign a dictionary with a different element type.");
Dictionary::operator=(p_dictionary);
}
_FORCE_INLINE_ TypedDictionary(const Variant &p_variant) :
TypedDictionary(Dictionary(p_variant)) {
}
_FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) {
set_typed(Variant::OBJECT, K::get_class_static(), Variant(), Variant::OBJECT, V::get_class_static(), Variant());
if (is_same_typed(p_dictionary)) {
Dictionary::operator=(p_dictionary);
} else {
assign(p_dictionary);
}
}
_FORCE_INLINE_ TypedDictionary() {
set_typed(Variant::OBJECT, K::get_class_static(), Variant(), Variant::OBJECT, V::get_class_static(), Variant());
}
_FORCE_INLINE_ TypedDictionary(std::initializer_list<KeyValue<K, V>> p_init) :
Dictionary() {
set_typed(Variant::OBJECT, K::get_class_static(), Variant(), Variant::OBJECT, V::get_class_static(), Variant());
for (const KeyValue<K, V> &E : p_init) {
operator[](E.key) = E.value;
}
}
};
//specialization for the rest of variant types
#define MAKE_TYPED_DICTIONARY_WITH_OBJECT(m_type, m_variant_type) \
template <typename T> \
class TypedDictionary<T, m_type> : public Dictionary { \
public: \
_FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) { \
ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign an dictionary with a different element type."); \
Dictionary::operator=(p_dictionary); \
} \
_FORCE_INLINE_ TypedDictionary(const Variant &p_variant) : \
TypedDictionary(Dictionary(p_variant)) { \
} \
_FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) { \
set_typed(Variant::OBJECT, T::get_class_static(), Variant(), m_variant_type, StringName(), Variant()); \
if (is_same_typed(p_dictionary)) { \
Dictionary::operator=(p_dictionary); \
} else { \
assign(p_dictionary); \
} \
} \
_FORCE_INLINE_ TypedDictionary() { \
set_typed(Variant::OBJECT, T::get_class_static(), Variant(), m_variant_type, StringName(), Variant()); \
} \
_FORCE_INLINE_ TypedDictionary(std::initializer_list<KeyValue<T, m_type>> p_init) : \
Dictionary() { \
set_typed(Variant::OBJECT, T::get_class_static(), Variant(), m_variant_type, StringName(), Variant()); \
for (const KeyValue<T, m_type> &E : p_init) { \
operator[](E.key) = E.value; \
} \
} \
}; \
template <typename T> \
class TypedDictionary<m_type, T> : public Dictionary { \
public: \
_FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) { \
ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign an dictionary with a different element type."); \
Dictionary::operator=(p_dictionary); \
} \
_FORCE_INLINE_ TypedDictionary(const Variant &p_variant) : \
TypedDictionary(Dictionary(p_variant)) { \
} \
_FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) { \
set_typed(m_variant_type, StringName(), Variant(), Variant::OBJECT, T::get_class_static(), Variant()); \
if (is_same_typed(p_dictionary)) { \
Dictionary::operator=(p_dictionary); \
} else { \
assign(p_dictionary); \
} \
} \
_FORCE_INLINE_ TypedDictionary() { \
set_typed(m_variant_type, StringName(), Variant(), Variant::OBJECT, T::get_class_static(), Variant()); \
} \
_FORCE_INLINE_ TypedDictionary(std::initializer_list<KeyValue<m_type, T>> p_init) : \
Dictionary() { \
set_typed(m_variant_type, StringName(), Variant(), Variant::OBJECT, std::remove_pointer<T>::type::get_class_static(), Variant()); \
for (const KeyValue<m_type, T> &E : p_init) { \
operator[](E.key) = E.value; \
} \
} \
};
#define MAKE_TYPED_DICTIONARY_EXPANDED(m_type_key, m_variant_type_key, m_type_value, m_variant_type_value) \
template <> \
class TypedDictionary<m_type_key, m_type_value> : public Dictionary { \
public: \
_FORCE_INLINE_ void operator=(const Dictionary &p_dictionary) { \
ERR_FAIL_COND_MSG(!is_same_typed(p_dictionary), "Cannot assign an dictionary with a different element type."); \
Dictionary::operator=(p_dictionary); \
} \
_FORCE_INLINE_ TypedDictionary(const Variant &p_variant) : \
TypedDictionary(Dictionary(p_variant)) { \
} \
_FORCE_INLINE_ TypedDictionary(const Dictionary &p_dictionary) { \
set_typed(m_variant_type_key, StringName(), Variant(), m_variant_type_value, StringName(), Variant()); \
if (is_same_typed(p_dictionary)) { \
Dictionary::operator=(p_dictionary); \
} else { \
assign(p_dictionary); \
} \
} \
_FORCE_INLINE_ TypedDictionary() { \
set_typed(m_variant_type_key, StringName(), Variant(), m_variant_type_value, StringName(), Variant()); \
} \
_FORCE_INLINE_ TypedDictionary(std::initializer_list<KeyValue<m_type_key, m_type_value>> p_init) : \
Dictionary() { \
set_typed(m_variant_type_key, StringName(), Variant(), m_variant_type_value, StringName(), Variant()); \
for (const KeyValue<m_type_key, m_type_value> &E : p_init) { \
operator[](E.key) = E.value; \
} \
} \
};
#define MAKE_TYPED_DICTIONARY_NIL(m_type, m_variant_type) \
MAKE_TYPED_DICTIONARY_WITH_OBJECT(m_type, m_variant_type) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, bool, Variant::BOOL) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, uint8_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, int8_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, uint16_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, int16_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, uint32_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, int32_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, uint64_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, int64_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, float, Variant::FLOAT) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, double, Variant::FLOAT) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, String, Variant::STRING) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Vector2, Variant::VECTOR2) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Vector2i, Variant::VECTOR2I) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Rect2, Variant::RECT2) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Rect2i, Variant::RECT2I) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Vector3, Variant::VECTOR3) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Vector3i, Variant::VECTOR3I) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Transform2D, Variant::TRANSFORM2D) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Plane, Variant::PLANE) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Quaternion, Variant::QUATERNION) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, AABB, Variant::AABB) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Basis, Variant::BASIS) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Transform3D, Variant::TRANSFORM3D) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Color, Variant::COLOR) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, StringName, Variant::STRING_NAME) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, NodePath, Variant::NODE_PATH) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, RID, Variant::RID) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Callable, Variant::CALLABLE) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Signal, Variant::SIGNAL) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Dictionary, Variant::DICTIONARY) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Array, Variant::ARRAY) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedByteArray, Variant::PACKED_BYTE_ARRAY) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedInt32Array, Variant::PACKED_INT32_ARRAY) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedInt64Array, Variant::PACKED_INT64_ARRAY) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedStringArray, Variant::PACKED_STRING_ARRAY) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedColorArray, Variant::PACKED_COLOR_ARRAY) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY) \
/*MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, IPAddress, Variant::STRING)*/
#define MAKE_TYPED_DICTIONARY(m_type, m_variant_type) \
MAKE_TYPED_DICTIONARY_EXPANDED(m_type, m_variant_type, Variant, Variant::NIL) \
MAKE_TYPED_DICTIONARY_NIL(m_type, m_variant_type)
MAKE_TYPED_DICTIONARY_NIL(Variant, Variant::NIL)
MAKE_TYPED_DICTIONARY(bool, Variant::BOOL)
MAKE_TYPED_DICTIONARY(uint8_t, Variant::INT)
MAKE_TYPED_DICTIONARY(int8_t, Variant::INT)
MAKE_TYPED_DICTIONARY(uint16_t, Variant::INT)
MAKE_TYPED_DICTIONARY(int16_t, Variant::INT)
MAKE_TYPED_DICTIONARY(uint32_t, Variant::INT)
MAKE_TYPED_DICTIONARY(int32_t, Variant::INT)
MAKE_TYPED_DICTIONARY(uint64_t, Variant::INT)
MAKE_TYPED_DICTIONARY(int64_t, Variant::INT)
MAKE_TYPED_DICTIONARY(float, Variant::FLOAT)
MAKE_TYPED_DICTIONARY(double, Variant::FLOAT)
MAKE_TYPED_DICTIONARY(String, Variant::STRING)
MAKE_TYPED_DICTIONARY(Vector2, Variant::VECTOR2)
MAKE_TYPED_DICTIONARY(Vector2i, Variant::VECTOR2I)
MAKE_TYPED_DICTIONARY(Rect2, Variant::RECT2)
MAKE_TYPED_DICTIONARY(Rect2i, Variant::RECT2I)
MAKE_TYPED_DICTIONARY(Vector3, Variant::VECTOR3)
MAKE_TYPED_DICTIONARY(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_DICTIONARY(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPED_DICTIONARY(Plane, Variant::PLANE)
MAKE_TYPED_DICTIONARY(Quaternion, Variant::QUATERNION)
MAKE_TYPED_DICTIONARY(AABB, Variant::AABB)
MAKE_TYPED_DICTIONARY(Basis, Variant::BASIS)
MAKE_TYPED_DICTIONARY(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPED_DICTIONARY(Color, Variant::COLOR)
MAKE_TYPED_DICTIONARY(StringName, Variant::STRING_NAME)
MAKE_TYPED_DICTIONARY(NodePath, Variant::NODE_PATH)
MAKE_TYPED_DICTIONARY(RID, Variant::RID)
MAKE_TYPED_DICTIONARY(Callable, Variant::CALLABLE)
MAKE_TYPED_DICTIONARY(Signal, Variant::SIGNAL)
MAKE_TYPED_DICTIONARY(Dictionary, Variant::DICTIONARY)
MAKE_TYPED_DICTIONARY(Array, Variant::ARRAY)
MAKE_TYPED_DICTIONARY(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
MAKE_TYPED_DICTIONARY(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
MAKE_TYPED_DICTIONARY(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
MAKE_TYPED_DICTIONARY(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
MAKE_TYPED_DICTIONARY(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
MAKE_TYPED_DICTIONARY(PackedStringArray, Variant::PACKED_STRING_ARRAY)
MAKE_TYPED_DICTIONARY(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPED_DICTIONARY(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPED_DICTIONARY(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
MAKE_TYPED_DICTIONARY(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY)
/*
MAKE_TYPED_DICTIONARY(IPAddress, Variant::STRING)
*/
#undef MAKE_TYPED_DICTIONARY
#undef MAKE_TYPED_DICTIONARY_NIL
#undef MAKE_TYPED_DICTIONARY_EXPANDED
#undef MAKE_TYPED_DICTIONARY_WITH_OBJECT
template <typename K, typename V>
struct PtrToArg<TypedDictionary<K, V>> {
_FORCE_INLINE_ static TypedDictionary<K, V> convert(const void *p_ptr) {
return TypedDictionary<K, V>(*reinterpret_cast<const Dictionary *>(p_ptr));
}
typedef Dictionary EncodeT;
_FORCE_INLINE_ static void encode(TypedDictionary<K, V> p_val, void *p_ptr) {
*(Dictionary *)p_ptr = p_val;
}
};
template <typename K, typename V>
struct PtrToArg<const TypedDictionary<K, V> &> {
typedef Dictionary EncodeT;
_FORCE_INLINE_ static TypedDictionary<K, V>
convert(const void *p_ptr) {
return TypedDictionary<K, V>(*reinterpret_cast<const Dictionary *>(p_ptr));
}
};
template <typename K, typename V>
struct GetTypeInfo<TypedDictionary<K, V>> {
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY;
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, vformat("%s;%s", K::get_class_static(), V::get_class_static()));
}
};
template <typename K, typename V>
struct GetTypeInfo<const TypedDictionary<K, V> &> {
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY;
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE;
static inline PropertyInfo get_class_info() {
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, vformat("%s;%s", K::get_class_static(), V::get_class_static()));
}
};
#define MAKE_TYPED_DICTIONARY_INFO_WITH_OBJECT(m_type, m_variant_type) \
template <typename T> \
struct GetTypeInfo<TypedDictionary<T, m_type>> { \
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY; \
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, \
vformat("%s;%s", T::get_class_static(), m_variant_type == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type).utf8().get_data())); \
} \
}; \
template <typename T> \
struct GetTypeInfo<const TypedDictionary<T, m_type> &> { \
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY; \
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, \
vformat("%s;%s", T::get_class_static(), m_variant_type == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type).utf8().get_data())); \
} \
}; \
template <typename T> \
struct GetTypeInfo<TypedDictionary<m_type, T>> { \
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY; \
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, \
vformat("%s;%s", m_variant_type == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type).utf8().get_data(), T::get_class_static())); \
} \
}; \
template <typename T> \
struct GetTypeInfo<const TypedDictionary<m_type, T> &> { \
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY; \
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, \
vformat("%s;%s", m_variant_type == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type).utf8().get_data(), T::get_class_static())); \
} \
};
#define MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type_key, m_variant_type_key, m_type_value, m_variant_type_value) \
template <> \
struct GetTypeInfo<TypedDictionary<m_type_key, m_type_value>> { \
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY; \
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, \
vformat("%s;%s", m_variant_type_key == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type_key).utf8().get_data(), \
m_variant_type_value == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type_value).utf8().get_data())); \
} \
}; \
template <> \
struct GetTypeInfo<const TypedDictionary<m_type_key, m_type_value> &> { \
static constexpr GDExtensionVariantType VARIANT_TYPE = GDEXTENSION_VARIANT_TYPE_DICTIONARY; \
static constexpr GDExtensionClassMethodArgumentMetadata METADATA = GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE; \
static inline PropertyInfo get_class_info() { \
return PropertyInfo(Variant::Type::DICTIONARY, String(), PROPERTY_HINT_DICTIONARY_TYPE, \
vformat("%s;%s", m_variant_type_key == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type_key).utf8().get_data(), \
m_variant_type_value == Variant::Type::NIL ? "Variant" : Variant::get_type_name(m_variant_type_value).utf8().get_data())); \
} \
};
#define MAKE_TYPED_DICTIONARY_INFO_NIL(m_type, m_variant_type) \
MAKE_TYPED_DICTIONARY_INFO_WITH_OBJECT(m_type, m_variant_type) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, bool, Variant::BOOL) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, uint8_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, int8_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, uint16_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, int16_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, uint32_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, int32_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, uint64_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, int64_t, Variant::INT) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, float, Variant::FLOAT) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, double, Variant::FLOAT) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, String, Variant::STRING) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Vector2, Variant::VECTOR2) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Vector2i, Variant::VECTOR2I) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Rect2, Variant::RECT2) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Rect2i, Variant::RECT2I) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Vector3, Variant::VECTOR3) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Vector3i, Variant::VECTOR3I) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Transform2D, Variant::TRANSFORM2D) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Plane, Variant::PLANE) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Quaternion, Variant::QUATERNION) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, AABB, Variant::AABB) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Basis, Variant::BASIS) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Transform3D, Variant::TRANSFORM3D) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Color, Variant::COLOR) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, StringName, Variant::STRING_NAME) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, NodePath, Variant::NODE_PATH) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, RID, Variant::RID) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Callable, Variant::CALLABLE) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Signal, Variant::SIGNAL) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Dictionary, Variant::DICTIONARY) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Array, Variant::ARRAY) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedByteArray, Variant::PACKED_BYTE_ARRAY) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedInt32Array, Variant::PACKED_INT32_ARRAY) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedInt64Array, Variant::PACKED_INT64_ARRAY) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedStringArray, Variant::PACKED_STRING_ARRAY) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, PackedColorArray, Variant::PACKED_COLOR_ARRAY) \
/* MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, IPAddress, Variant::STRING) */
#define MAKE_TYPED_DICTIONARY_INFO(m_type, m_variant_type) \
MAKE_TYPED_DICTIONARY_INFO_EXPANDED(m_type, m_variant_type, Variant, Variant::NIL) \
MAKE_TYPED_DICTIONARY_INFO_NIL(m_type, m_variant_type)
MAKE_TYPED_DICTIONARY_INFO_NIL(Variant, Variant::NIL)
MAKE_TYPED_DICTIONARY_INFO(bool, Variant::BOOL)
MAKE_TYPED_DICTIONARY_INFO(uint8_t, Variant::INT)
MAKE_TYPED_DICTIONARY_INFO(int8_t, Variant::INT)
MAKE_TYPED_DICTIONARY_INFO(uint16_t, Variant::INT)
MAKE_TYPED_DICTIONARY_INFO(int16_t, Variant::INT)
MAKE_TYPED_DICTIONARY_INFO(uint32_t, Variant::INT)
MAKE_TYPED_DICTIONARY_INFO(int32_t, Variant::INT)
MAKE_TYPED_DICTIONARY_INFO(uint64_t, Variant::INT)
MAKE_TYPED_DICTIONARY_INFO(int64_t, Variant::INT)
MAKE_TYPED_DICTIONARY_INFO(float, Variant::FLOAT)
MAKE_TYPED_DICTIONARY_INFO(double, Variant::FLOAT)
MAKE_TYPED_DICTIONARY_INFO(String, Variant::STRING)
MAKE_TYPED_DICTIONARY_INFO(Vector2, Variant::VECTOR2)
MAKE_TYPED_DICTIONARY_INFO(Vector2i, Variant::VECTOR2I)
MAKE_TYPED_DICTIONARY_INFO(Rect2, Variant::RECT2)
MAKE_TYPED_DICTIONARY_INFO(Rect2i, Variant::RECT2I)
MAKE_TYPED_DICTIONARY_INFO(Vector3, Variant::VECTOR3)
MAKE_TYPED_DICTIONARY_INFO(Vector3i, Variant::VECTOR3I)
MAKE_TYPED_DICTIONARY_INFO(Transform2D, Variant::TRANSFORM2D)
MAKE_TYPED_DICTIONARY_INFO(Plane, Variant::PLANE)
MAKE_TYPED_DICTIONARY_INFO(Quaternion, Variant::QUATERNION)
MAKE_TYPED_DICTIONARY_INFO(AABB, Variant::AABB)
MAKE_TYPED_DICTIONARY_INFO(Basis, Variant::BASIS)
MAKE_TYPED_DICTIONARY_INFO(Transform3D, Variant::TRANSFORM3D)
MAKE_TYPED_DICTIONARY_INFO(Color, Variant::COLOR)
MAKE_TYPED_DICTIONARY_INFO(StringName, Variant::STRING_NAME)
MAKE_TYPED_DICTIONARY_INFO(NodePath, Variant::NODE_PATH)
MAKE_TYPED_DICTIONARY_INFO(RID, Variant::RID)
MAKE_TYPED_DICTIONARY_INFO(Callable, Variant::CALLABLE)
MAKE_TYPED_DICTIONARY_INFO(Signal, Variant::SIGNAL)
MAKE_TYPED_DICTIONARY_INFO(Dictionary, Variant::DICTIONARY)
MAKE_TYPED_DICTIONARY_INFO(Array, Variant::ARRAY)
MAKE_TYPED_DICTIONARY_INFO(PackedByteArray, Variant::PACKED_BYTE_ARRAY)
MAKE_TYPED_DICTIONARY_INFO(PackedInt32Array, Variant::PACKED_INT32_ARRAY)
MAKE_TYPED_DICTIONARY_INFO(PackedInt64Array, Variant::PACKED_INT64_ARRAY)
MAKE_TYPED_DICTIONARY_INFO(PackedFloat32Array, Variant::PACKED_FLOAT32_ARRAY)
MAKE_TYPED_DICTIONARY_INFO(PackedFloat64Array, Variant::PACKED_FLOAT64_ARRAY)
MAKE_TYPED_DICTIONARY_INFO(PackedStringArray, Variant::PACKED_STRING_ARRAY)
MAKE_TYPED_DICTIONARY_INFO(PackedVector2Array, Variant::PACKED_VECTOR2_ARRAY)
MAKE_TYPED_DICTIONARY_INFO(PackedVector3Array, Variant::PACKED_VECTOR3_ARRAY)
MAKE_TYPED_DICTIONARY_INFO(PackedVector4Array, Variant::PACKED_VECTOR4_ARRAY)
MAKE_TYPED_DICTIONARY_INFO(PackedColorArray, Variant::PACKED_COLOR_ARRAY)
/*
MAKE_TYPED_DICTIONARY_INFO(IPAddress, Variant::STRING)
*/
#undef MAKE_TYPED_DICTIONARY_INFO
#undef MAKE_TYPED_DICTIONARY_INFO_NIL
#undef MAKE_TYPED_DICTIONARY_INFO_EXPANDED
#undef MAKE_TYPED_DICTIONARY_INFO_WITH_OBJECT
} // namespace godot

View File

@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_VARIANT_HPP
#define GODOT_VARIANT_HPP
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/variant/array.hpp>
#include <godot_cpp/variant/builtin_types.hpp>
#include <godot_cpp/variant/variant_size.hpp>
@@ -49,7 +49,6 @@ class Variant {
friend class GDExtensionBinding;
friend class MethodBind;
friend class VariantInternal;
static void init_bindings();
@@ -145,7 +144,7 @@ private:
static GDExtensionTypeFromVariantConstructorFunc to_type_constructor[VARIANT_MAX];
public:
_FORCE_INLINE_ GDExtensionVariantPtr _native_ptr() const { return const_cast<uint8_t (*)[GODOT_CPP_VARIANT_SIZE]>(&opaque); }
_FORCE_INLINE_ GDExtensionVariantPtr _native_ptr() const { return const_cast<uint8_t(*)[GODOT_CPP_VARIANT_SIZE]>(&opaque); }
Variant();
Variant(std::nullptr_t n) :
Variant() {}
@@ -265,8 +264,6 @@ public:
operator PackedColorArray() const;
operator PackedVector4Array() const;
Object *get_validated_object() const;
Variant &operator=(const Variant &other);
Variant &operator=(Variant &&other);
bool operator==(const Variant &other) const;
@@ -358,66 +355,6 @@ String vformat(const String &p_text, const VarArgs... p_args) {
return p_text % args_array;
}
Variant &Array::Iterator::operator*() const {
return *elem_ptr;
}
Variant *Array::Iterator::operator->() const {
return elem_ptr;
}
Array::Iterator &Array::Iterator::operator++() {
elem_ptr++;
return *this;
}
Array::Iterator &Array::Iterator::operator--() {
elem_ptr--;
return *this;
}
const Variant &Array::ConstIterator::operator*() const {
return *elem_ptr;
}
const Variant *Array::ConstIterator::operator->() const {
return elem_ptr;
}
Array::ConstIterator &Array::ConstIterator::operator++() {
elem_ptr++;
return *this;
}
Array::ConstIterator &Array::ConstIterator::operator--() {
elem_ptr--;
return *this;
}
Array::Iterator Array::begin() {
return Array::Iterator(ptrw());
}
Array::Iterator Array::end() {
return Array::Iterator(ptrw() + size());
}
Array::ConstIterator Array::begin() const {
return Array::ConstIterator(ptr());
}
Array::ConstIterator Array::end() const {
return Array::ConstIterator(ptr() + size());
}
Array::Array(std::initializer_list<Variant> p_init) :
Array() {
ERR_FAIL_COND(resize(p_init.size()) != 0);
size_t i = 0;
for (const Variant &element : p_init) {
set(i++, element);
}
}
#include <godot_cpp/variant/builtin_vararg_methods.hpp>
#ifdef REAL_T_IS_DOUBLE
@@ -427,3 +364,5 @@ using PackedRealArray = PackedFloat32Array;
#endif // REAL_T_IS_DOUBLE
} // namespace godot
#endif // GODOT_VARIANT_HPP

View File

@@ -1,506 +0,0 @@
/**************************************************************************/
/* variant_internal.hpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include <gdextension_interface.h>
#include <godot_cpp/variant/variant.hpp>
namespace godot {
// For use when you want to access the internal pointer of a Variant directly.
// Use with caution. You need to be sure that the type is correct.
namespace internal {
template <typename T>
struct VariantInternalType {};
template <>
struct VariantInternalType<bool> {
static constexpr Variant::Type type = Variant::BOOL;
};
template <>
struct VariantInternalType<int64_t> {
static constexpr Variant::Type type = Variant::INT;
};
template <>
struct VariantInternalType<double> {
static constexpr Variant::Type type = Variant::FLOAT;
};
template <>
struct VariantInternalType<String> {
static constexpr Variant::Type type = Variant::STRING;
};
template <>
struct VariantInternalType<Vector2> {
static constexpr Variant::Type type = Variant::VECTOR2;
};
template <>
struct VariantInternalType<Vector2i> {
static constexpr Variant::Type type = Variant::VECTOR2I;
};
template <>
struct VariantInternalType<Rect2> {
static constexpr Variant::Type type = Variant::RECT2;
};
template <>
struct VariantInternalType<Rect2i> {
static constexpr Variant::Type type = Variant::RECT2I;
};
template <>
struct VariantInternalType<Vector3> {
static constexpr Variant::Type type = Variant::VECTOR3;
};
template <>
struct VariantInternalType<Vector3i> {
static constexpr Variant::Type type = Variant::VECTOR3I;
};
template <>
struct VariantInternalType<Transform2D> {
static constexpr Variant::Type type = Variant::TRANSFORM2D;
};
template <>
struct VariantInternalType<Vector4> {
static constexpr Variant::Type type = Variant::VECTOR4;
};
template <>
struct VariantInternalType<Vector4i> {
static constexpr Variant::Type type = Variant::VECTOR4I;
};
template <>
struct VariantInternalType<Plane> {
static constexpr Variant::Type type = Variant::PLANE;
};
template <>
struct VariantInternalType<Quaternion> {
static constexpr Variant::Type type = Variant::QUATERNION;
};
template <>
struct VariantInternalType<AABB> {
static constexpr Variant::Type type = Variant::AABB;
};
template <>
struct VariantInternalType<Basis> {
static constexpr Variant::Type type = Variant::BASIS;
};
template <>
struct VariantInternalType<Transform3D> {
static constexpr Variant::Type type = Variant::TRANSFORM3D;
};
template <>
struct VariantInternalType<Projection> {
static constexpr Variant::Type type = Variant::PROJECTION;
};
template <>
struct VariantInternalType<Color> {
static constexpr Variant::Type type = Variant::COLOR;
};
template <>
struct VariantInternalType<StringName> {
static constexpr Variant::Type type = Variant::STRING_NAME;
};
template <>
struct VariantInternalType<NodePath> {
static constexpr Variant::Type type = Variant::NODE_PATH;
};
template <>
struct VariantInternalType<RID> {
static constexpr Variant::Type type = Variant::RID;
};
template <>
struct VariantInternalType<Object *> {
static constexpr Variant::Type type = Variant::OBJECT;
};
template <>
struct VariantInternalType<Callable> {
static constexpr Variant::Type type = Variant::CALLABLE;
};
template <>
struct VariantInternalType<Signal> {
static constexpr Variant::Type type = Variant::SIGNAL;
};
template <>
struct VariantInternalType<Dictionary> {
static constexpr Variant::Type type = Variant::DICTIONARY;
};
template <>
struct VariantInternalType<Array> {
static constexpr Variant::Type type = Variant::ARRAY;
};
template <>
struct VariantInternalType<PackedByteArray> {
static constexpr Variant::Type type = Variant::PACKED_BYTE_ARRAY;
};
template <>
struct VariantInternalType<PackedInt32Array> {
static constexpr Variant::Type type = Variant::PACKED_INT32_ARRAY;
};
template <>
struct VariantInternalType<PackedInt64Array> {
static constexpr Variant::Type type = Variant::PACKED_INT64_ARRAY;
};
template <>
struct VariantInternalType<PackedFloat32Array> {
static constexpr Variant::Type type = Variant::PACKED_FLOAT32_ARRAY;
};
template <>
struct VariantInternalType<PackedFloat64Array> {
static constexpr Variant::Type type = Variant::PACKED_FLOAT64_ARRAY;
};
template <>
struct VariantInternalType<PackedStringArray> {
static constexpr Variant::Type type = Variant::PACKED_STRING_ARRAY;
};
template <>
struct VariantInternalType<PackedVector2Array> {
static constexpr Variant::Type type = Variant::PACKED_VECTOR2_ARRAY;
};
template <>
struct VariantInternalType<PackedVector3Array> {
static constexpr Variant::Type type = Variant::PACKED_VECTOR3_ARRAY;
};
template <>
struct VariantInternalType<PackedColorArray> {
static constexpr Variant::Type type = Variant::PACKED_COLOR_ARRAY;
};
template <>
struct VariantInternalType<PackedVector4Array> {
static constexpr Variant::Type type = Variant::PACKED_VECTOR4_ARRAY;
};
} //namespace internal
class VariantInternal {
friend class Variant;
static GDExtensionVariantGetInternalPtrFunc get_internal_func[Variant::VARIANT_MAX];
static void init_bindings();
public:
template <typename T>
_FORCE_INLINE_ static T *get_internal_value(Variant *v) {
return static_cast<T *>(get_internal_func[internal::VariantInternalType<T>::type](v));
}
template <typename T>
_FORCE_INLINE_ static const T *get_internal_value(const Variant *v) {
return static_cast<const T *>(get_internal_func[internal::VariantInternalType<T>::type](const_cast<Variant *>(v)));
}
// Atomic types.
_FORCE_INLINE_ static bool *get_bool(Variant *v) { return get_internal_value<bool>(v); }
_FORCE_INLINE_ static const bool *get_bool(const Variant *v) { return get_internal_value<bool>(v); }
_FORCE_INLINE_ static int64_t *get_int(Variant *v) { return get_internal_value<int64_t>(v); }
_FORCE_INLINE_ static const int64_t *get_int(const Variant *v) { return get_internal_value<int64_t>(v); }
_FORCE_INLINE_ static double *get_float(Variant *v) { return get_internal_value<double>(v); }
_FORCE_INLINE_ static const double *get_float(const Variant *v) { return get_internal_value<double>(v); }
_FORCE_INLINE_ static String *get_string(Variant *v) { return get_internal_value<String>(v); }
_FORCE_INLINE_ static const String *get_string(const Variant *v) { return get_internal_value<String>(v); }
// Math types.
_FORCE_INLINE_ static Vector2 *get_vector2(Variant *v) { return get_internal_value<Vector2>(v); }
_FORCE_INLINE_ static const Vector2 *get_vector2(const Variant *v) { return get_internal_value<Vector2>(v); }
_FORCE_INLINE_ static Vector2i *get_vector2i(Variant *v) { return get_internal_value<Vector2i>(v); }
_FORCE_INLINE_ static const Vector2i *get_vector2i(const Variant *v) { return get_internal_value<Vector2i>(v); }
_FORCE_INLINE_ static Rect2 *get_rect2(Variant *v) { return get_internal_value<Rect2>(v); }
_FORCE_INLINE_ static const Rect2 *get_rect2(const Variant *v) { return get_internal_value<Rect2>(v); }
_FORCE_INLINE_ static Rect2i *get_rect2i(Variant *v) { return get_internal_value<Rect2i>(v); }
_FORCE_INLINE_ static const Rect2i *get_rect2i(const Variant *v) { return get_internal_value<Rect2i>(v); }
_FORCE_INLINE_ static Vector3 *get_vector3(Variant *v) { return get_internal_value<Vector3>(v); }
_FORCE_INLINE_ static const Vector3 *get_vector3(const Variant *v) { return get_internal_value<Vector3>(v); }
_FORCE_INLINE_ static Vector3i *get_vector3i(Variant *v) { return get_internal_value<Vector3i>(v); }
_FORCE_INLINE_ static const Vector3i *get_vector3i(const Variant *v) { return get_internal_value<Vector3i>(v); }
_FORCE_INLINE_ static Vector4 *get_vector4(Variant *v) { return get_internal_value<Vector4>(v); }
_FORCE_INLINE_ static const Vector4 *get_vector4(const Variant *v) { return get_internal_value<Vector4>(v); }
_FORCE_INLINE_ static Vector4i *get_vector4i(Variant *v) { return get_internal_value<Vector4i>(v); }
_FORCE_INLINE_ static const Vector4i *get_vector4i(const Variant *v) { return get_internal_value<Vector4i>(v); }
_FORCE_INLINE_ static Transform2D *get_transform2d(Variant *v) { return get_internal_value<Transform2D>(v); }
_FORCE_INLINE_ static const Transform2D *get_transform2d(const Variant *v) { return get_internal_value<Transform2D>(v); }
_FORCE_INLINE_ static Plane *get_plane(Variant *v) { return get_internal_value<Plane>(v); }
_FORCE_INLINE_ static const Plane *get_plane(const Variant *v) { return get_internal_value<Plane>(v); }
_FORCE_INLINE_ static Quaternion *get_quaternion(Variant *v) { return get_internal_value<Quaternion>(v); }
_FORCE_INLINE_ static const Quaternion *get_quaternion(const Variant *v) { return get_internal_value<Quaternion>(v); }
_FORCE_INLINE_ static AABB *get_aabb(Variant *v) { return get_internal_value<AABB>(v); }
_FORCE_INLINE_ static const AABB *get_aabb(const Variant *v) { return get_internal_value<AABB>(v); }
_FORCE_INLINE_ static Basis *get_basis(Variant *v) { return get_internal_value<Basis>(v); }
_FORCE_INLINE_ static const Basis *get_basis(const Variant *v) { return get_internal_value<Basis>(v); }
_FORCE_INLINE_ static Transform3D *get_transform(Variant *v) { return get_internal_value<Transform3D>(v); }
_FORCE_INLINE_ static const Transform3D *get_transform(const Variant *v) { return get_internal_value<Transform3D>(v); }
_FORCE_INLINE_ static Projection *get_projection(Variant *v) { return get_internal_value<Projection>(v); }
_FORCE_INLINE_ static const Projection *get_projection(const Variant *v) { return get_internal_value<Projection>(v); }
// Misc types.
_FORCE_INLINE_ static Color *get_color(Variant *v) { return get_internal_value<Color>(v); }
_FORCE_INLINE_ static const Color *get_color(const Variant *v) { return get_internal_value<Color>(v); }
_FORCE_INLINE_ static StringName *get_string_name(Variant *v) { return get_internal_value<StringName>(v); }
_FORCE_INLINE_ static const StringName *get_string_name(const Variant *v) { return get_internal_value<StringName>(v); }
_FORCE_INLINE_ static NodePath *get_node_path(Variant *v) { return get_internal_value<NodePath>(v); }
_FORCE_INLINE_ static const NodePath *get_node_path(const Variant *v) { return get_internal_value<NodePath>(v); }
_FORCE_INLINE_ static RID *get_rid(Variant *v) { return get_internal_value<RID>(v); }
_FORCE_INLINE_ static const RID *get_rid(const Variant *v) { return get_internal_value<RID>(v); }
_FORCE_INLINE_ static Callable *get_callable(Variant *v) { return get_internal_value<Callable>(v); }
_FORCE_INLINE_ static const Callable *get_callable(const Variant *v) { return get_internal_value<Callable>(v); }
_FORCE_INLINE_ static Signal *get_signal(Variant *v) { return get_internal_value<Signal>(v); }
_FORCE_INLINE_ static const Signal *get_signal(const Variant *v) { return get_internal_value<Signal>(v); }
_FORCE_INLINE_ static Dictionary *get_dictionary(Variant *v) { return get_internal_value<Dictionary>(v); }
_FORCE_INLINE_ static const Dictionary *get_dictionary(const Variant *v) { return get_internal_value<Dictionary>(v); }
_FORCE_INLINE_ static Array *get_array(Variant *v) { return get_internal_value<Array>(v); }
_FORCE_INLINE_ static const Array *get_array(const Variant *v) { return get_internal_value<Array>(v); }
// Typed arrays.
_FORCE_INLINE_ static PackedByteArray *get_byte_array(Variant *v) { return get_internal_value<PackedByteArray>(v); }
_FORCE_INLINE_ static const PackedByteArray *get_byte_array(const Variant *v) { return get_internal_value<PackedByteArray>(v); }
_FORCE_INLINE_ static PackedInt32Array *get_int32_array(Variant *v) { return get_internal_value<PackedInt32Array>(v); }
_FORCE_INLINE_ static const PackedInt32Array *get_int32_array(const Variant *v) { return get_internal_value<PackedInt32Array>(v); }
_FORCE_INLINE_ static PackedInt64Array *get_int64_array(Variant *v) { return get_internal_value<PackedInt64Array>(v); }
_FORCE_INLINE_ static const PackedInt64Array *get_int64_array(const Variant *v) { return get_internal_value<PackedInt64Array>(v); }
_FORCE_INLINE_ static PackedFloat32Array *get_float32_array(Variant *v) { return get_internal_value<PackedFloat32Array>(v); }
_FORCE_INLINE_ static const PackedFloat32Array *get_float32_array(const Variant *v) { return get_internal_value<PackedFloat32Array>(v); }
_FORCE_INLINE_ static PackedFloat64Array *get_float64_array(Variant *v) { return get_internal_value<PackedFloat64Array>(v); }
_FORCE_INLINE_ static const PackedFloat64Array *get_float64_array(const Variant *v) { return get_internal_value<PackedFloat64Array>(v); }
_FORCE_INLINE_ static PackedStringArray *get_string_array(Variant *v) { return get_internal_value<PackedStringArray>(v); }
_FORCE_INLINE_ static const PackedStringArray *get_string_array(const Variant *v) { return get_internal_value<PackedStringArray>(v); }
_FORCE_INLINE_ static PackedVector2Array *get_vector2_array(Variant *v) { return get_internal_value<PackedVector2Array>(v); }
_FORCE_INLINE_ static const PackedVector2Array *get_vector2_array(const Variant *v) { return get_internal_value<PackedVector2Array>(v); }
_FORCE_INLINE_ static PackedVector3Array *get_vector3_array(Variant *v) { return get_internal_value<PackedVector3Array>(v); }
_FORCE_INLINE_ static const PackedVector3Array *get_vector3_array(const Variant *v) { return get_internal_value<PackedVector3Array>(v); }
_FORCE_INLINE_ static PackedColorArray *get_color_array(Variant *v) { return get_internal_value<PackedColorArray>(v); }
_FORCE_INLINE_ static const PackedColorArray *get_color_array(const Variant *v) { return get_internal_value<PackedColorArray>(v); }
_FORCE_INLINE_ static PackedVector4Array *get_vector4_array(Variant *v) { return get_internal_value<PackedVector4Array>(v); }
_FORCE_INLINE_ static const PackedVector4Array *get_vector4_array(const Variant *v) { return get_internal_value<PackedVector4Array>(v); }
_FORCE_INLINE_ static Object **get_object(Variant *v) { return get_internal_value<Object *>(v); }
_FORCE_INLINE_ static const Object **get_object(const Variant *v) { return (const Object **)get_internal_value<Object *>(v); }
_FORCE_INLINE_ static void *get_opaque_pointer(Variant *v) {
switch (v->get_type()) {
case Variant::NIL:
return nullptr;
case Variant::BOOL:
return get_bool(v);
case Variant::INT:
return get_int(v);
case Variant::FLOAT:
return get_float(v);
case Variant::STRING:
return get_string(v);
case Variant::VECTOR2:
return get_vector2(v);
case Variant::VECTOR2I:
return get_vector2i(v);
case Variant::VECTOR3:
return get_vector3(v);
case Variant::VECTOR3I:
return get_vector3i(v);
case Variant::VECTOR4:
return get_vector4(v);
case Variant::VECTOR4I:
return get_vector4i(v);
case Variant::RECT2:
return get_rect2(v);
case Variant::RECT2I:
return get_rect2i(v);
case Variant::TRANSFORM3D:
return get_transform(v);
case Variant::PROJECTION:
return get_projection(v);
case Variant::TRANSFORM2D:
return get_transform2d(v);
case Variant::QUATERNION:
return get_quaternion(v);
case Variant::PLANE:
return get_plane(v);
case Variant::BASIS:
return get_basis(v);
case Variant::AABB:
return get_aabb(v);
case Variant::COLOR:
return get_color(v);
case Variant::STRING_NAME:
return get_string_name(v);
case Variant::NODE_PATH:
return get_node_path(v);
case Variant::RID:
return get_rid(v);
case Variant::CALLABLE:
return get_callable(v);
case Variant::SIGNAL:
return get_signal(v);
case Variant::DICTIONARY:
return get_dictionary(v);
case Variant::ARRAY:
return get_array(v);
case Variant::PACKED_BYTE_ARRAY:
return get_byte_array(v);
case Variant::PACKED_INT32_ARRAY:
return get_int32_array(v);
case Variant::PACKED_INT64_ARRAY:
return get_int64_array(v);
case Variant::PACKED_FLOAT32_ARRAY:
return get_float32_array(v);
case Variant::PACKED_FLOAT64_ARRAY:
return get_float64_array(v);
case Variant::PACKED_STRING_ARRAY:
return get_string_array(v);
case Variant::PACKED_VECTOR2_ARRAY:
return get_vector2_array(v);
case Variant::PACKED_VECTOR3_ARRAY:
return get_vector3_array(v);
case Variant::PACKED_COLOR_ARRAY:
return get_color_array(v);
case Variant::PACKED_VECTOR4_ARRAY:
return get_vector4_array(v);
case Variant::OBJECT:
return get_object(v);
case Variant::VARIANT_MAX:
ERR_FAIL_V(nullptr);
}
ERR_FAIL_V(nullptr);
}
_FORCE_INLINE_ static const void *get_opaque_pointer(const Variant *v) {
switch (v->get_type()) {
case Variant::NIL:
return nullptr;
case Variant::BOOL:
return get_bool(v);
case Variant::INT:
return get_int(v);
case Variant::FLOAT:
return get_float(v);
case Variant::STRING:
return get_string(v);
case Variant::VECTOR2:
return get_vector2(v);
case Variant::VECTOR2I:
return get_vector2i(v);
case Variant::VECTOR3:
return get_vector3(v);
case Variant::VECTOR3I:
return get_vector3i(v);
case Variant::VECTOR4:
return get_vector4(v);
case Variant::VECTOR4I:
return get_vector4i(v);
case Variant::RECT2:
return get_rect2(v);
case Variant::RECT2I:
return get_rect2i(v);
case Variant::TRANSFORM3D:
return get_transform(v);
case Variant::PROJECTION:
return get_projection(v);
case Variant::TRANSFORM2D:
return get_transform2d(v);
case Variant::QUATERNION:
return get_quaternion(v);
case Variant::PLANE:
return get_plane(v);
case Variant::BASIS:
return get_basis(v);
case Variant::AABB:
return get_aabb(v);
case Variant::COLOR:
return get_color(v);
case Variant::STRING_NAME:
return get_string_name(v);
case Variant::NODE_PATH:
return get_node_path(v);
case Variant::RID:
return get_rid(v);
case Variant::CALLABLE:
return get_callable(v);
case Variant::SIGNAL:
return get_signal(v);
case Variant::DICTIONARY:
return get_dictionary(v);
case Variant::ARRAY:
return get_array(v);
case Variant::PACKED_BYTE_ARRAY:
return get_byte_array(v);
case Variant::PACKED_INT32_ARRAY:
return get_int32_array(v);
case Variant::PACKED_INT64_ARRAY:
return get_int64_array(v);
case Variant::PACKED_FLOAT32_ARRAY:
return get_float32_array(v);
case Variant::PACKED_FLOAT64_ARRAY:
return get_float64_array(v);
case Variant::PACKED_STRING_ARRAY:
return get_string_array(v);
case Variant::PACKED_VECTOR2_ARRAY:
return get_vector2_array(v);
case Variant::PACKED_VECTOR3_ARRAY:
return get_vector3_array(v);
case Variant::PACKED_COLOR_ARRAY:
return get_color_array(v);
case Variant::PACKED_VECTOR4_ARRAY:
return get_vector4_array(v);
case Variant::OBJECT:
return get_object(v);
case Variant::VARIANT_MAX:
ERR_FAIL_V(nullptr);
}
ERR_FAIL_V(nullptr);
}
};
template <typename T>
struct VariantGetInternalPtr {
static internal::VariantInternalType<T> *get_ptr(Variant *v) { return VariantInternal::get_internal_value<T>(v); }
static const internal::VariantInternalType<T> *get_ptr(const Variant *v) { return VariantInternal::get_internal_value<T>(v); }
};
template <typename T>
struct can_set_variant_internal_value {
static const bool value = true;
};
template <>
struct can_set_variant_internal_value<Object *> {
static const bool value = false;
};
template <typename T>
struct VariantInternalAccessor {
static _FORCE_INLINE_ const T &get(const Variant *v) { return *VariantInternal::get_internal_value<T>(v); }
// Enable set() only for those types where we can set (all but Object *).
template <typename U = T, typename = std::enable_if_t<can_set_variant_internal_value<U>::value>>
static _FORCE_INLINE_ void set(Variant *v, const internal::VariantInternalType<U> &p_value) {
*VariantInternal::get_internal_value<U>(v) = p_value;
}
};
template <typename T, std::enable_if_t<can_set_variant_internal_value<T>::value>>
struct VariantDefaultInitializer {
static _FORCE_INLINE_ void init(Variant *v) { *VariantInternal::get_internal_value<T>(v) = T(); }
};
} // namespace godot

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_VECTOR2_HPP
#define GODOT_VECTOR2_HPP
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/math.hpp>
@@ -61,13 +62,13 @@ struct [[nodiscard]] Vector2 {
real_t coord[2] = { 0 };
};
_FORCE_INLINE_ real_t &operator[](int p_axis) {
DEV_ASSERT((unsigned int)p_axis < 2);
return coord[p_axis];
_FORCE_INLINE_ real_t &operator[](int p_idx) {
DEV_ASSERT((unsigned int)p_idx < 2);
return coord[p_idx];
}
_FORCE_INLINE_ const real_t &operator[](int p_axis) const {
DEV_ASSERT((unsigned int)p_axis < 2);
return coord[p_axis];
_FORCE_INLINE_ const real_t &operator[](int p_idx) const {
DEV_ASSERT((unsigned int)p_idx < 2);
return coord[p_idx];
}
_FORCE_INLINE_ Vector2::Axis min_axis_index() const {
@@ -84,7 +85,7 @@ struct [[nodiscard]] Vector2 {
real_t length() const;
real_t length_squared() const;
Vector2 limit_length(real_t p_len = 1.0) const;
Vector2 limit_length(const real_t p_len = 1.0) const;
Vector2 min(const Vector2 &p_vector2) const {
return Vector2(MIN(x, p_vector2.x), MIN(y, p_vector2.y));
@@ -110,20 +111,19 @@ struct [[nodiscard]] Vector2 {
real_t dot(const Vector2 &p_other) const;
real_t cross(const Vector2 &p_other) const;
Vector2 posmod(real_t p_mod) const;
Vector2 posmod(const real_t p_mod) const;
Vector2 posmodv(const Vector2 &p_modv) const;
Vector2 project(const Vector2 &p_to) const;
Vector2 plane_project(real_t p_d, const Vector2 &p_vec) const;
Vector2 plane_project(const real_t p_d, const Vector2 &p_vec) const;
_FORCE_INLINE_ Vector2 lerp(const Vector2 &p_to, real_t p_weight) const;
_FORCE_INLINE_ Vector2 slerp(const Vector2 &p_to, real_t p_weight) const;
_FORCE_INLINE_ Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight) const;
_FORCE_INLINE_ Vector2 cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const;
_FORCE_INLINE_ Vector2 bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, real_t p_t) const;
_FORCE_INLINE_ Vector2 bezier_derivative(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, real_t p_t) const;
_FORCE_INLINE_ Vector2 lerp(const Vector2 &p_to, const real_t p_weight) const;
_FORCE_INLINE_ Vector2 slerp(const Vector2 &p_to, const real_t p_weight) const;
_FORCE_INLINE_ Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight) const;
_FORCE_INLINE_ Vector2 cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const;
_FORCE_INLINE_ Vector2 bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const;
Vector2 move_toward(const Vector2 &p_to, real_t p_delta) const;
Vector2 move_toward(const Vector2 &p_to, const real_t p_delta) const;
Vector2 slide(const Vector2 &p_normal) const;
Vector2 bounce(const Vector2 &p_normal) const;
@@ -139,16 +139,16 @@ struct [[nodiscard]] Vector2 {
void operator-=(const Vector2 &p_v);
Vector2 operator*(const Vector2 &p_v1) const;
Vector2 operator*(real_t p_rvalue) const;
void operator*=(real_t p_rvalue);
void operator*=(const Vector2 &p_rvalue) { *this = *this * p_rvalue; }
Vector2 operator*(const real_t &rvalue) const;
void operator*=(const real_t &rvalue);
void operator*=(const Vector2 &rvalue) { *this = *this * rvalue; }
Vector2 operator/(const Vector2 &p_v1) const;
Vector2 operator/(real_t p_rvalue) const;
Vector2 operator/(const real_t &rvalue) const;
void operator/=(real_t p_rvalue);
void operator/=(const Vector2 &p_rvalue) { *this = *this / p_rvalue; }
void operator/=(const real_t &rvalue);
void operator/=(const Vector2 &rvalue) { *this = *this / rvalue; }
Vector2 operator-() const;
@@ -161,13 +161,13 @@ struct [[nodiscard]] Vector2 {
bool operator>=(const Vector2 &p_vec2) const { return x == p_vec2.x ? (y >= p_vec2.y) : (x > p_vec2.x); }
real_t angle() const;
static Vector2 from_angle(real_t p_angle);
static Vector2 from_angle(const real_t p_angle);
_FORCE_INLINE_ Vector2 abs() const {
return Vector2(Math::abs(x), Math::abs(y));
}
Vector2 rotated(real_t p_by) const;
Vector2 rotated(const real_t p_by) const;
Vector2 orthogonal() const {
return Vector2(y, -x);
}
@@ -186,13 +186,13 @@ struct [[nodiscard]] Vector2 {
operator Vector2i() const;
_FORCE_INLINE_ Vector2() {}
_FORCE_INLINE_ Vector2(real_t p_x, real_t p_y) {
_FORCE_INLINE_ Vector2(const real_t p_x, const real_t p_y) {
x = p_x;
y = p_y;
}
};
_FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2 &p_vec) const {
_FORCE_INLINE_ Vector2 Vector2::plane_project(const real_t p_d, const Vector2 &p_vec) const {
return p_vec - *this * (dot(p_vec) - p_d);
}
@@ -218,26 +218,26 @@ _FORCE_INLINE_ Vector2 Vector2::operator*(const Vector2 &p_v1) const {
return Vector2(x * p_v1.x, y * p_v1.y);
}
_FORCE_INLINE_ Vector2 Vector2::operator*(real_t p_rvalue) const {
return Vector2(x * p_rvalue, y * p_rvalue);
_FORCE_INLINE_ Vector2 Vector2::operator*(const real_t &rvalue) const {
return Vector2(x * rvalue, y * rvalue);
}
_FORCE_INLINE_ void Vector2::operator*=(real_t p_rvalue) {
x *= p_rvalue;
y *= p_rvalue;
_FORCE_INLINE_ void Vector2::operator*=(const real_t &rvalue) {
x *= rvalue;
y *= rvalue;
}
_FORCE_INLINE_ Vector2 Vector2::operator/(const Vector2 &p_v1) const {
return Vector2(x / p_v1.x, y / p_v1.y);
}
_FORCE_INLINE_ Vector2 Vector2::operator/(real_t p_rvalue) const {
return Vector2(x / p_rvalue, y / p_rvalue);
_FORCE_INLINE_ Vector2 Vector2::operator/(const real_t &rvalue) const {
return Vector2(x / rvalue, y / rvalue);
}
_FORCE_INLINE_ void Vector2::operator/=(real_t p_rvalue) {
x /= p_rvalue;
y /= p_rvalue;
_FORCE_INLINE_ void Vector2::operator/=(const real_t &rvalue) {
x /= rvalue;
y /= rvalue;
}
_FORCE_INLINE_ Vector2 Vector2::operator-() const {
@@ -252,14 +252,16 @@ _FORCE_INLINE_ bool Vector2::operator!=(const Vector2 &p_vec2) const {
return x != p_vec2.x || y != p_vec2.y;
}
Vector2 Vector2::lerp(const Vector2 &p_to, real_t p_weight) const {
Vector2 Vector2::lerp(const Vector2 &p_to, const real_t p_weight) const {
Vector2 res = *this;
res.x = Math::lerp(res.x, p_to.x, p_weight);
res.y = Math::lerp(res.y, p_to.y, p_weight);
res.x += (p_weight * (p_to.x - x));
res.y += (p_weight * (p_to.y - y));
return res;
}
Vector2 Vector2::slerp(const Vector2 &p_to, real_t p_weight) const {
Vector2 Vector2::slerp(const Vector2 &p_to, const real_t p_weight) const {
real_t start_length_sq = length_squared();
real_t end_length_sq = p_to.length_squared();
if (unlikely(start_length_sq == 0.0f || end_length_sq == 0.0f)) {
@@ -272,32 +274,31 @@ Vector2 Vector2::slerp(const Vector2 &p_to, real_t p_weight) const {
return rotated(angle * p_weight) * (result_length / start_length);
}
Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight) const {
Vector2 Vector2::cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight) const {
Vector2 res = *this;
res.x = Math::cubic_interpolate(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight);
res.y = Math::cubic_interpolate(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight);
return res;
}
Vector2 Vector2::cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const {
Vector2 Vector2::cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const {
Vector2 res = *this;
res.x = Math::cubic_interpolate_in_time(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
res.y = Math::cubic_interpolate_in_time(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
return res;
}
Vector2 Vector2::bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, real_t p_t) const {
Vector2 Vector2::bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const {
Vector2 res = *this;
res.x = Math::bezier_interpolate(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t);
res.y = Math::bezier_interpolate(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t);
return res;
}
Vector2 Vector2::bezier_derivative(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, real_t p_t) const {
Vector2 res = *this;
res.x = Math::bezier_derivative(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t);
res.y = Math::bezier_derivative(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t);
return res;
/* Formula from Wikipedia article on Bezier curves. */
real_t omt = (1.0 - p_t);
real_t omt2 = omt * omt;
real_t omt3 = omt2 * omt;
real_t t2 = p_t * p_t;
real_t t3 = t2 * p_t;
return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3;
}
Vector2 Vector2::direction_to(const Vector2 &p_to) const {
@@ -309,19 +310,19 @@ Vector2 Vector2::direction_to(const Vector2 &p_to) const {
// Multiplication operators required to workaround issues with LLVM using implicit conversion
// to Vector2i instead for integers where it should not.
_FORCE_INLINE_ Vector2 operator*(float p_scalar, const Vector2 &p_vec) {
_FORCE_INLINE_ Vector2 operator*(const float p_scalar, const Vector2 &p_vec) {
return p_vec * p_scalar;
}
_FORCE_INLINE_ Vector2 operator*(double p_scalar, const Vector2 &p_vec) {
_FORCE_INLINE_ Vector2 operator*(const double p_scalar, const Vector2 &p_vec) {
return p_vec * p_scalar;
}
_FORCE_INLINE_ Vector2 operator*(int32_t p_scalar, const Vector2 &p_vec) {
_FORCE_INLINE_ Vector2 operator*(const int32_t p_scalar, const Vector2 &p_vec) {
return p_vec * p_scalar;
}
_FORCE_INLINE_ Vector2 operator*(int64_t p_scalar, const Vector2 &p_vec) {
_FORCE_INLINE_ Vector2 operator*(const int64_t p_scalar, const Vector2 &p_vec) {
return p_vec * p_scalar;
}
@@ -329,3 +330,5 @@ typedef Vector2 Size2;
typedef Vector2 Point2;
} // namespace godot
#endif // GODOT_VECTOR2_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_VECTOR2I_HPP
#define GODOT_VECTOR2I_HPP
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/math.hpp>
@@ -61,13 +62,13 @@ struct [[nodiscard]] Vector2i {
int32_t coord[2] = { 0 };
};
_FORCE_INLINE_ int32_t &operator[](int p_axis) {
DEV_ASSERT((unsigned int)p_axis < 2);
return coord[p_axis];
_FORCE_INLINE_ int32_t &operator[](int p_idx) {
DEV_ASSERT((unsigned int)p_idx < 2);
return coord[p_idx];
}
_FORCE_INLINE_ const int32_t &operator[](int p_axis) const {
DEV_ASSERT((unsigned int)p_axis < 2);
return coord[p_axis];
_FORCE_INLINE_ const int32_t &operator[](int p_idx) const {
DEV_ASSERT((unsigned int)p_idx < 2);
return coord[p_idx];
}
_FORCE_INLINE_ Vector2i::Axis min_axis_index() const {
@@ -94,30 +95,22 @@ struct [[nodiscard]] Vector2i {
return Vector2i(MAX(x, p_scalar), MAX(y, p_scalar));
}
double distance_to(const Vector2i &p_to) const {
return (p_to - *this).length();
}
int64_t distance_squared_to(const Vector2i &p_to) const {
return (p_to - *this).length_squared();
}
Vector2i operator+(const Vector2i &p_v) const;
void operator+=(const Vector2i &p_v);
Vector2i operator-(const Vector2i &p_v) const;
void operator-=(const Vector2i &p_v);
Vector2i operator*(const Vector2i &p_v1) const;
Vector2i operator*(int32_t p_rvalue) const;
void operator*=(int32_t p_rvalue);
Vector2i operator*(const int32_t &rvalue) const;
void operator*=(const int32_t &rvalue);
Vector2i operator/(const Vector2i &p_v1) const;
Vector2i operator/(int32_t p_rvalue) const;
void operator/=(int32_t p_rvalue);
Vector2i operator/(const int32_t &rvalue) const;
void operator/=(const int32_t &rvalue);
Vector2i operator%(const Vector2i &p_v1) const;
Vector2i operator%(int32_t p_rvalue) const;
void operator%=(int32_t p_rvalue);
Vector2i operator%(const int32_t &rvalue) const;
void operator%=(const int32_t &rvalue);
Vector2i operator-() const;
bool operator<(const Vector2i &p_vec2) const { return (x == p_vec2.x) ? (y < p_vec2.y) : (x < p_vec2.x); }
@@ -132,19 +125,22 @@ struct [[nodiscard]] Vector2i {
int64_t length_squared() const;
double length() const;
int64_t distance_squared_to(const Vector2i &p_to) const;
double distance_to(const Vector2i &p_to) const;
real_t aspect() const { return width / (real_t)height; }
Vector2i sign() const { return Vector2i(SIGN(x), SIGN(y)); }
Vector2i abs() const { return Vector2i(Math::abs(x), Math::abs(y)); }
Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const;
Vector2i clampi(int32_t p_min, int32_t p_max) const;
Vector2i snapped(const Vector2i &p_step) const;
Vector2i snappedi(int32_t p_step) const;
Vector2i clamp(const Vector2i &p_min, const Vector2i &p_max) const;
Vector2i clampi(int32_t p_min, int32_t p_max) const;
operator String() const;
operator Vector2() const;
inline Vector2i() {}
inline Vector2i(int32_t p_x, int32_t p_y) {
inline Vector2i(const int32_t p_x, const int32_t p_y) {
x = p_x;
y = p_y;
}
@@ -152,19 +148,19 @@ struct [[nodiscard]] Vector2i {
// Multiplication operators required to workaround issues with LLVM using implicit conversion.
_FORCE_INLINE_ Vector2i operator*(int32_t p_scalar, const Vector2i &p_vector) {
_FORCE_INLINE_ Vector2i operator*(const int32_t p_scalar, const Vector2i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector2i operator*(int64_t p_scalar, const Vector2i &p_vector) {
_FORCE_INLINE_ Vector2i operator*(const int64_t p_scalar, const Vector2i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector2i operator*(float p_scalar, const Vector2i &p_vector) {
_FORCE_INLINE_ Vector2i operator*(const float p_scalar, const Vector2i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector2i operator*(double p_scalar, const Vector2i &p_vector) {
_FORCE_INLINE_ Vector2i operator*(const double p_scalar, const Vector2i &p_vector) {
return p_vector * p_scalar;
}
@@ -172,3 +168,5 @@ typedef Vector2i Size2i;
typedef Vector2i Point2i;
} // namespace godot
#endif // GODOT_VECTOR2I_HPP

View File

@@ -28,14 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_VECTOR3_HPP
#define GODOT_VECTOR3_HPP
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/math.hpp>
#include <godot_cpp/variant/string.hpp>
namespace godot {
class String;
struct Basis;
struct Vector2;
struct Vector3i;
@@ -59,12 +60,12 @@ struct [[nodiscard]] Vector3 {
real_t coord[3] = { 0 };
};
_FORCE_INLINE_ const real_t &operator[](int p_axis) const {
_FORCE_INLINE_ const real_t &operator[](const int p_axis) const {
DEV_ASSERT((unsigned int)p_axis < 3);
return coord[p_axis];
}
_FORCE_INLINE_ real_t &operator[](int p_axis) {
_FORCE_INLINE_ real_t &operator[](const int p_axis) {
DEV_ASSERT((unsigned int)p_axis < 3);
return coord[p_axis];
}
@@ -100,38 +101,36 @@ struct [[nodiscard]] Vector3 {
_FORCE_INLINE_ Vector3 normalized() const;
_FORCE_INLINE_ bool is_normalized() const;
_FORCE_INLINE_ Vector3 inverse() const;
Vector3 limit_length(real_t p_len = 1.0) const;
Vector3 limit_length(const real_t p_len = 1.0) const;
_FORCE_INLINE_ void zero();
void snap(const Vector3 &p_step);
void snapf(real_t p_step);
Vector3 snapped(const Vector3 &p_step) const;
Vector3 snappedf(real_t p_step) const;
void snap(const Vector3 p_val);
void snapf(real_t p_val);
Vector3 snapped(const Vector3 p_val) const;
Vector3 snappedf(real_t p_val) const;
void rotate(const Vector3 &p_axis, real_t p_angle);
Vector3 rotated(const Vector3 &p_axis, real_t p_angle) const;
void rotate(const Vector3 &p_axis, const real_t p_angle);
Vector3 rotated(const Vector3 &p_axis, const real_t p_angle) const;
/* Static Methods between 2 vector3s */
_FORCE_INLINE_ Vector3 lerp(const Vector3 &p_to, real_t p_weight) const;
_FORCE_INLINE_ Vector3 slerp(const Vector3 &p_to, real_t p_weight) const;
_FORCE_INLINE_ Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight) const;
_FORCE_INLINE_ Vector3 cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const;
_FORCE_INLINE_ Vector3 bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, real_t p_t) const;
_FORCE_INLINE_ Vector3 bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, real_t p_t) const;
_FORCE_INLINE_ Vector3 lerp(const Vector3 &p_to, const real_t p_weight) const;
_FORCE_INLINE_ Vector3 slerp(const Vector3 &p_to, const real_t p_weight) const;
_FORCE_INLINE_ Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const;
_FORCE_INLINE_ Vector3 cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const;
_FORCE_INLINE_ Vector3 bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const;
Vector3 move_toward(const Vector3 &p_to, real_t p_delta) const;
Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const;
Vector2 octahedron_encode() const;
static Vector3 octahedron_decode(const Vector2 &p_oct);
Vector2 octahedron_tangent_encode(float p_sign) const;
static Vector3 octahedron_tangent_decode(const Vector2 &p_oct, float *r_sign);
Vector2 octahedron_tangent_encode(const float sign) const;
static Vector3 octahedron_tangent_decode(const Vector2 &p_oct, float *sign);
_FORCE_INLINE_ Vector3 cross(const Vector3 &p_with) const;
_FORCE_INLINE_ real_t dot(const Vector3 &p_with) const;
Basis outer(const Vector3 &p_with) const;
_FORCE_INLINE_ Vector3 get_any_perpendicular() const;
_FORCE_INLINE_ Vector3 abs() const;
_FORCE_INLINE_ Vector3 floor() const;
@@ -144,7 +143,7 @@ struct [[nodiscard]] Vector3 {
_FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const;
_FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const;
_FORCE_INLINE_ Vector3 posmod(real_t p_mod) const;
_FORCE_INLINE_ Vector3 posmod(const real_t p_mod) const;
_FORCE_INLINE_ Vector3 posmodv(const Vector3 &p_modv) const;
_FORCE_INLINE_ Vector3 project(const Vector3 &p_to) const;
@@ -171,10 +170,10 @@ struct [[nodiscard]] Vector3 {
_FORCE_INLINE_ Vector3 &operator/=(const Vector3 &p_v);
_FORCE_INLINE_ Vector3 operator/(const Vector3 &p_v) const;
_FORCE_INLINE_ Vector3 &operator*=(real_t p_scalar);
_FORCE_INLINE_ Vector3 operator*(real_t p_scalar) const;
_FORCE_INLINE_ Vector3 &operator/=(real_t p_scalar);
_FORCE_INLINE_ Vector3 operator/(real_t p_scalar) const;
_FORCE_INLINE_ Vector3 &operator*=(const real_t p_scalar);
_FORCE_INLINE_ Vector3 operator*(const real_t p_scalar) const;
_FORCE_INLINE_ Vector3 &operator/=(const real_t p_scalar);
_FORCE_INLINE_ Vector3 operator/(const real_t p_scalar) const;
_FORCE_INLINE_ Vector3 operator-() const;
@@ -189,7 +188,7 @@ struct [[nodiscard]] Vector3 {
operator Vector3i() const;
_FORCE_INLINE_ Vector3() {}
_FORCE_INLINE_ Vector3(real_t p_x, real_t p_y, real_t p_z) {
_FORCE_INLINE_ Vector3(const real_t p_x, const real_t p_y, const real_t p_z) {
x = p_x;
y = p_y;
z = p_z;
@@ -229,15 +228,14 @@ Vector3 Vector3::round() const {
return Vector3(Math::round(x), Math::round(y), Math::round(z));
}
Vector3 Vector3::lerp(const Vector3 &p_to, real_t p_weight) const {
Vector3 res = *this;
res.x = Math::lerp(res.x, p_to.x, p_weight);
res.y = Math::lerp(res.y, p_to.y, p_weight);
res.z = Math::lerp(res.z, p_to.z, p_weight);
return res;
Vector3 Vector3::lerp(const Vector3 &p_to, const real_t p_weight) const {
return Vector3(
x + (p_weight * (p_to.x - x)),
y + (p_weight * (p_to.y - y)),
z + (p_weight * (p_to.z - z)));
}
Vector3 Vector3::slerp(const Vector3 &p_to, real_t p_weight) const {
Vector3 Vector3::slerp(const Vector3 &p_to, const real_t p_weight) const {
// This method seems more complicated than it really is, since we write out
// the internals of some methods for efficiency (mainly, checking length).
real_t start_length_sq = length_squared();
@@ -259,7 +257,7 @@ Vector3 Vector3::slerp(const Vector3 &p_to, real_t p_weight) const {
return rotated(axis, angle * p_weight) * (result_length / start_length);
}
Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight) const {
Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const {
Vector3 res = *this;
res.x = Math::cubic_interpolate(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight);
res.y = Math::cubic_interpolate(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight);
@@ -267,7 +265,7 @@ Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, c
return res;
}
Vector3 Vector3::cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const {
Vector3 Vector3::cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const {
Vector3 res = *this;
res.x = Math::cubic_interpolate_in_time(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
res.y = Math::cubic_interpolate_in_time(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight, p_b_t, p_pre_a_t, p_post_b_t);
@@ -275,20 +273,17 @@ Vector3 Vector3::cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_
return res;
}
Vector3 Vector3::bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, real_t p_t) const {
Vector3 Vector3::bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const {
Vector3 res = *this;
res.x = Math::bezier_interpolate(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t);
res.y = Math::bezier_interpolate(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t);
res.z = Math::bezier_interpolate(res.z, p_control_1.z, p_control_2.z, p_end.z, p_t);
return res;
}
Vector3 Vector3::bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, real_t p_t) const {
Vector3 res = *this;
res.x = Math::bezier_derivative(res.x, p_control_1.x, p_control_2.x, p_end.x, p_t);
res.y = Math::bezier_derivative(res.y, p_control_1.y, p_control_2.y, p_end.y, p_t);
res.z = Math::bezier_derivative(res.z, p_control_1.z, p_control_2.z, p_end.z, p_t);
return res;
/* Formula from Wikipedia article on Bezier curves. */
real_t omt = (1.0 - p_t);
real_t omt2 = omt * omt;
real_t omt3 = omt2 * omt;
real_t t2 = p_t * p_t;
real_t t3 = t2 * p_t;
return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3;
}
real_t Vector3::distance_to(const Vector3 &p_to) const {
@@ -299,7 +294,7 @@ real_t Vector3::distance_squared_to(const Vector3 &p_to) const {
return (p_to - *this).length_squared();
}
Vector3 Vector3::posmod(real_t p_mod) const {
Vector3 Vector3::posmod(const real_t p_mod) const {
return Vector3(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod), Math::fposmod(z, p_mod));
}
@@ -328,16 +323,6 @@ Vector3 Vector3::direction_to(const Vector3 &p_to) const {
return ret;
}
Vector3 Vector3::get_any_perpendicular() const {
// Return the any perpendicular vector by cross product with the Vector3.RIGHT or Vector3.UP,
// whichever has the greater angle to the current vector with the sign of each element positive.
// The only essence is "to avoid being parallel to the current vector", and there is no mathematical basis for using Vector3.RIGHT and Vector3.UP,
// since it could be a different vector depending on the prior branching code Math::abs(x) <= Math::abs(y) && Math::abs(x) <= Math::abs(z).
// However, it would be reasonable to use any of the axes of the basis, as it is simpler to calculate.
ERR_FAIL_COND_V_MSG(is_zero_approx(), Vector3(0, 0, 0), "The Vector3 must not be zero.");
return cross((Math::abs(x) <= Math::abs(y) && Math::abs(x) <= Math::abs(z)) ? Vector3(1, 0, 0) : Vector3(0, 1, 0)).normalized();
}
/* Operators */
Vector3 &Vector3::operator+=(const Vector3 &p_v) {
@@ -384,7 +369,7 @@ Vector3 Vector3::operator/(const Vector3 &p_v) const {
return Vector3(x / p_v.x, y / p_v.y, z / p_v.z);
}
Vector3 &Vector3::operator*=(real_t p_scalar) {
Vector3 &Vector3::operator*=(const real_t p_scalar) {
x *= p_scalar;
y *= p_scalar;
z *= p_scalar;
@@ -394,34 +379,34 @@ Vector3 &Vector3::operator*=(real_t p_scalar) {
// Multiplication operators required to workaround issues with LLVM using implicit conversion
// to Vector3i instead for integers where it should not.
_FORCE_INLINE_ Vector3 operator*(float p_scalar, const Vector3 &p_vec) {
_FORCE_INLINE_ Vector3 operator*(const float p_scalar, const Vector3 &p_vec) {
return p_vec * p_scalar;
}
_FORCE_INLINE_ Vector3 operator*(double p_scalar, const Vector3 &p_vec) {
_FORCE_INLINE_ Vector3 operator*(const double p_scalar, const Vector3 &p_vec) {
return p_vec * p_scalar;
}
_FORCE_INLINE_ Vector3 operator*(int32_t p_scalar, const Vector3 &p_vec) {
_FORCE_INLINE_ Vector3 operator*(const int32_t p_scalar, const Vector3 &p_vec) {
return p_vec * p_scalar;
}
_FORCE_INLINE_ Vector3 operator*(int64_t p_scalar, const Vector3 &p_vec) {
_FORCE_INLINE_ Vector3 operator*(const int64_t p_scalar, const Vector3 &p_vec) {
return p_vec * p_scalar;
}
Vector3 Vector3::operator*(real_t p_scalar) const {
Vector3 Vector3::operator*(const real_t p_scalar) const {
return Vector3(x * p_scalar, y * p_scalar, z * p_scalar);
}
Vector3 &Vector3::operator/=(real_t p_scalar) {
Vector3 &Vector3::operator/=(const real_t p_scalar) {
x /= p_scalar;
y /= p_scalar;
z /= p_scalar;
return *this;
}
Vector3 Vector3::operator/(real_t p_scalar) const {
Vector3 Vector3::operator/(const real_t p_scalar) const {
return Vector3(x / p_scalar, y / p_scalar, z / p_scalar);
}
@@ -535,9 +520,9 @@ void Vector3::zero() {
// slide returns the component of the vector along the given plane, specified by its normal vector.
Vector3 Vector3::slide(const Vector3 &p_normal) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 " + p_normal.operator String() + " must be normalized.");
ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized.");
#endif
return *this - p_normal * dot(p_normal);
return *this - p_normal * this->dot(p_normal);
}
Vector3 Vector3::bounce(const Vector3 &p_normal) const {
@@ -546,9 +531,11 @@ Vector3 Vector3::bounce(const Vector3 &p_normal) const {
Vector3 Vector3::reflect(const Vector3 &p_normal) const {
#ifdef MATH_CHECKS
ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 " + p_normal.operator String() + " must be normalized.");
ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized.");
#endif
return 2.0f * p_normal * dot(p_normal) - *this;
return 2.0f * p_normal * this->dot(p_normal) - *this;
}
} // namespace godot
#endif // GODOT_VECTOR3_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_VECTOR3I_HPP
#define GODOT_VECTOR3I_HPP
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/math.hpp>
@@ -57,12 +58,12 @@ struct [[nodiscard]] Vector3i {
int32_t coord[3] = { 0 };
};
_FORCE_INLINE_ const int32_t &operator[](int p_axis) const {
_FORCE_INLINE_ const int32_t &operator[](const int p_axis) const {
DEV_ASSERT((unsigned int)p_axis < 3);
return coord[p_axis];
}
_FORCE_INLINE_ int32_t &operator[](int p_axis) {
_FORCE_INLINE_ int32_t &operator[](const int p_axis) {
DEV_ASSERT((unsigned int)p_axis < 3);
return coord[p_axis];
}
@@ -89,17 +90,17 @@ struct [[nodiscard]] Vector3i {
_FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const;
_FORCE_INLINE_ int64_t distance_squared_to(const Vector3i &p_to) const;
_FORCE_INLINE_ double distance_to(const Vector3i &p_to) const;
_FORCE_INLINE_ void zero();
_FORCE_INLINE_ Vector3i abs() const;
_FORCE_INLINE_ Vector3i sign() const;
Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const;
Vector3i clampi(int32_t p_min, int32_t p_max) const;
Vector3i snapped(const Vector3i &p_step) const;
Vector3i snappedi(int32_t p_step) const;
_FORCE_INLINE_ double distance_to(const Vector3i &p_to) const;
_FORCE_INLINE_ int64_t distance_squared_to(const Vector3i &p_to) const;
Vector3i clamp(const Vector3i &p_min, const Vector3i &p_max) const;
Vector3i clampi(int32_t p_min, int32_t p_max) const;
/* Operators */
@@ -114,12 +115,12 @@ struct [[nodiscard]] Vector3i {
_FORCE_INLINE_ Vector3i &operator%=(const Vector3i &p_v);
_FORCE_INLINE_ Vector3i operator%(const Vector3i &p_v) const;
_FORCE_INLINE_ Vector3i &operator*=(int32_t p_scalar);
_FORCE_INLINE_ Vector3i operator*(int32_t p_scalar) const;
_FORCE_INLINE_ Vector3i &operator/=(int32_t p_scalar);
_FORCE_INLINE_ Vector3i operator/(int32_t p_scalar) const;
_FORCE_INLINE_ Vector3i &operator%=(int32_t p_scalar);
_FORCE_INLINE_ Vector3i operator%(int32_t p_scalar) const;
_FORCE_INLINE_ Vector3i &operator*=(const int32_t p_scalar);
_FORCE_INLINE_ Vector3i operator*(const int32_t p_scalar) const;
_FORCE_INLINE_ Vector3i &operator/=(const int32_t p_scalar);
_FORCE_INLINE_ Vector3i operator/(const int32_t p_scalar) const;
_FORCE_INLINE_ Vector3i &operator%=(const int32_t p_scalar);
_FORCE_INLINE_ Vector3i operator%(const int32_t p_scalar) const;
_FORCE_INLINE_ Vector3i operator-() const;
@@ -134,7 +135,7 @@ struct [[nodiscard]] Vector3i {
operator Vector3() const;
_FORCE_INLINE_ Vector3i() {}
_FORCE_INLINE_ Vector3i(int32_t p_x, int32_t p_y, int32_t p_z) {
_FORCE_INLINE_ Vector3i(const int32_t p_x, const int32_t p_y, const int32_t p_z) {
x = p_x;
y = p_y;
z = p_z;
@@ -149,20 +150,20 @@ double Vector3i::length() const {
return Math::sqrt((double)length_squared());
}
Vector3i Vector3i::abs() const {
return Vector3i(Math::abs(x), Math::abs(y), Math::abs(z));
}
Vector3i Vector3i::sign() const {
return Vector3i(SIGN(x), SIGN(y), SIGN(z));
int64_t Vector3i::distance_squared_to(const Vector3i &p_to) const {
return (p_to - *this).length_squared();
}
double Vector3i::distance_to(const Vector3i &p_to) const {
return (p_to - *this).length();
}
int64_t Vector3i::distance_squared_to(const Vector3i &p_to) const {
return (p_to - *this).length_squared();
Vector3i Vector3i::abs() const {
return Vector3i(Math::abs(x), Math::abs(y), Math::abs(z));
}
Vector3i Vector3i::sign() const {
return Vector3i(SIGN(x), SIGN(y), SIGN(z));
}
/* Operators */
@@ -222,54 +223,54 @@ Vector3i Vector3i::operator%(const Vector3i &p_v) const {
return Vector3i(x % p_v.x, y % p_v.y, z % p_v.z);
}
Vector3i &Vector3i::operator*=(int32_t p_scalar) {
Vector3i &Vector3i::operator*=(const int32_t p_scalar) {
x *= p_scalar;
y *= p_scalar;
z *= p_scalar;
return *this;
}
Vector3i Vector3i::operator*(int32_t p_scalar) const {
Vector3i Vector3i::operator*(const int32_t p_scalar) const {
return Vector3i(x * p_scalar, y * p_scalar, z * p_scalar);
}
// Multiplication operators required to workaround issues with LLVM using implicit conversion.
_FORCE_INLINE_ Vector3i operator*(int32_t p_scalar, const Vector3i &p_vector) {
_FORCE_INLINE_ Vector3i operator*(const int32_t p_scalar, const Vector3i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector3i operator*(int64_t p_scalar, const Vector3i &p_vector) {
_FORCE_INLINE_ Vector3i operator*(const int64_t p_scalar, const Vector3i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector3i operator*(float p_scalar, const Vector3i &p_vector) {
_FORCE_INLINE_ Vector3i operator*(const float p_scalar, const Vector3i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector3i operator*(double p_scalar, const Vector3i &p_vector) {
_FORCE_INLINE_ Vector3i operator*(const double p_scalar, const Vector3i &p_vector) {
return p_vector * p_scalar;
}
Vector3i &Vector3i::operator/=(int32_t p_scalar) {
Vector3i &Vector3i::operator/=(const int32_t p_scalar) {
x /= p_scalar;
y /= p_scalar;
z /= p_scalar;
return *this;
}
Vector3i Vector3i::operator/(int32_t p_scalar) const {
Vector3i Vector3i::operator/(const int32_t p_scalar) const {
return Vector3i(x / p_scalar, y / p_scalar, z / p_scalar);
}
Vector3i &Vector3i::operator%=(int32_t p_scalar) {
Vector3i &Vector3i::operator%=(const int32_t p_scalar) {
x %= p_scalar;
y %= p_scalar;
z %= p_scalar;
return *this;
}
Vector3i Vector3i::operator%(int32_t p_scalar) const {
Vector3i Vector3i::operator%(const int32_t p_scalar) const {
return Vector3i(x % p_scalar, y % p_scalar, z % p_scalar);
}
@@ -338,3 +339,5 @@ void Vector3i::zero() {
}
} // namespace godot
#endif // GODOT_VECTOR3I_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_VECTOR4_HPP
#define GODOT_VECTOR4_HPP
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/math.hpp>
@@ -36,7 +37,6 @@
namespace godot {
class String;
struct Vector4i;
struct [[nodiscard]] Vector4 {
static const int AXIS_COUNT = 4;
@@ -55,14 +55,15 @@ struct [[nodiscard]] Vector4 {
real_t z;
real_t w;
};
[[deprecated("Use coord instead")]] real_t components[4];
real_t coord[4] = { 0, 0, 0, 0 };
};
_FORCE_INLINE_ real_t &operator[](int p_axis) {
_FORCE_INLINE_ real_t &operator[](const int p_axis) {
DEV_ASSERT((unsigned int)p_axis < 4);
return coord[p_axis];
}
_FORCE_INLINE_ const real_t &operator[](int p_axis) const {
_FORCE_INLINE_ const real_t &operator[](const int p_axis) const {
DEV_ASSERT((unsigned int)p_axis < 4);
return coord[p_axis];
}
@@ -104,11 +105,11 @@ struct [[nodiscard]] Vector4 {
Vector4 floor() const;
Vector4 ceil() const;
Vector4 round() const;
Vector4 lerp(const Vector4 &p_to, real_t p_weight) const;
Vector4 cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, real_t p_weight) const;
Vector4 cubic_interpolate_in_time(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, real_t p_weight, real_t p_b_t, real_t p_pre_a_t, real_t p_post_b_t) const;
Vector4 lerp(const Vector4 &p_to, const real_t p_weight) const;
Vector4 cubic_interpolate(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight) const;
Vector4 cubic_interpolate_in_time(const Vector4 &p_b, const Vector4 &p_pre_a, const Vector4 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const;
Vector4 posmod(real_t p_mod) const;
Vector4 posmod(const real_t p_mod) const;
Vector4 posmodv(const Vector4 &p_modv) const;
void snap(const Vector4 &p_step);
void snapf(real_t p_step);
@@ -124,15 +125,15 @@ struct [[nodiscard]] Vector4 {
_FORCE_INLINE_ void operator-=(const Vector4 &p_vec4);
_FORCE_INLINE_ void operator*=(const Vector4 &p_vec4);
_FORCE_INLINE_ void operator/=(const Vector4 &p_vec4);
_FORCE_INLINE_ void operator*=(real_t p_s);
_FORCE_INLINE_ void operator/=(real_t p_s);
_FORCE_INLINE_ void operator*=(const real_t &s);
_FORCE_INLINE_ void operator/=(const real_t &s);
_FORCE_INLINE_ Vector4 operator+(const Vector4 &p_vec4) const;
_FORCE_INLINE_ Vector4 operator-(const Vector4 &p_vec4) const;
_FORCE_INLINE_ Vector4 operator*(const Vector4 &p_vec4) const;
_FORCE_INLINE_ Vector4 operator/(const Vector4 &p_vec4) const;
_FORCE_INLINE_ Vector4 operator-() const;
_FORCE_INLINE_ Vector4 operator*(real_t p_s) const;
_FORCE_INLINE_ Vector4 operator/(real_t p_s) const;
_FORCE_INLINE_ Vector4 operator*(const real_t &s) const;
_FORCE_INLINE_ Vector4 operator/(const real_t &s) const;
_FORCE_INLINE_ bool operator==(const Vector4 &p_vec4) const;
_FORCE_INLINE_ bool operator!=(const Vector4 &p_vec4) const;
@@ -142,14 +143,28 @@ struct [[nodiscard]] Vector4 {
_FORCE_INLINE_ bool operator<=(const Vector4 &p_vec4) const;
operator String() const;
operator Vector4i() const;
_FORCE_INLINE_ Vector4() {}
_FORCE_INLINE_ Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) {
x = p_x;
y = p_y;
z = p_z;
w = p_w;
_FORCE_INLINE_ Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) :
x(p_x),
y(p_y),
z(p_z),
w(p_w) {
}
Vector4(const Vector4 &p_vec4) :
x(p_vec4.x),
y(p_vec4.y),
z(p_vec4.z),
w(p_vec4.w) {
}
void operator=(const Vector4 &p_vec4) {
x = p_vec4.x;
y = p_vec4.y;
z = p_vec4.z;
w = p_vec4.w;
}
};
@@ -188,15 +203,15 @@ void Vector4::operator/=(const Vector4 &p_vec4) {
z /= p_vec4.z;
w /= p_vec4.w;
}
void Vector4::operator*=(real_t p_s) {
x *= p_s;
y *= p_s;
z *= p_s;
w *= p_s;
void Vector4::operator*=(const real_t &s) {
x *= s;
y *= s;
z *= s;
w *= s;
}
void Vector4::operator/=(real_t p_s) {
*this *= 1.0f / p_s;
void Vector4::operator/=(const real_t &s) {
*this *= 1.0f / s;
}
Vector4 Vector4::operator+(const Vector4 &p_vec4) const {
@@ -219,12 +234,12 @@ Vector4 Vector4::operator-() const {
return Vector4(-x, -y, -z, -w);
}
Vector4 Vector4::operator*(real_t p_s) const {
return Vector4(x * p_s, y * p_s, z * p_s, w * p_s);
Vector4 Vector4::operator*(const real_t &s) const {
return Vector4(x * s, y * s, z * s, w * s);
}
Vector4 Vector4::operator/(real_t p_s) const {
return *this * (1.0f / p_s);
Vector4 Vector4::operator/(const real_t &s) const {
return *this * (1.0f / s);
}
bool Vector4::operator==(const Vector4 &p_vec4) const {
@@ -287,20 +302,22 @@ bool Vector4::operator>=(const Vector4 &p_v) const {
return x > p_v.x;
}
_FORCE_INLINE_ Vector4 operator*(float p_scalar, const Vector4 &p_vec) {
_FORCE_INLINE_ Vector4 operator*(const float p_scalar, const Vector4 &p_vec) {
return p_vec * p_scalar;
}
_FORCE_INLINE_ Vector4 operator*(double p_scalar, const Vector4 &p_vec) {
_FORCE_INLINE_ Vector4 operator*(const double p_scalar, const Vector4 &p_vec) {
return p_vec * p_scalar;
}
_FORCE_INLINE_ Vector4 operator*(int32_t p_scalar, const Vector4 &p_vec) {
_FORCE_INLINE_ Vector4 operator*(const int32_t p_scalar, const Vector4 &p_vec) {
return p_vec * p_scalar;
}
_FORCE_INLINE_ Vector4 operator*(int64_t p_scalar, const Vector4 &p_vec) {
_FORCE_INLINE_ Vector4 operator*(const int64_t p_scalar, const Vector4 &p_vec) {
return p_vec * p_scalar;
}
} // namespace godot
#endif // GODOT_VECTOR4_HPP

View File

@@ -28,7 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#ifndef GODOT_VECTOR4I_HPP
#define GODOT_VECTOR4I_HPP
#include <godot_cpp/core/error_macros.hpp>
#include <godot_cpp/core/math.hpp>
@@ -59,12 +60,12 @@ struct [[nodiscard]] Vector4i {
int32_t coord[4] = { 0 };
};
_FORCE_INLINE_ const int32_t &operator[](int p_axis) const {
_FORCE_INLINE_ const int32_t &operator[](const int p_axis) const {
DEV_ASSERT((unsigned int)p_axis < 4);
return coord[p_axis];
}
_FORCE_INLINE_ int32_t &operator[](int p_axis) {
_FORCE_INLINE_ int32_t &operator[](const int p_axis) {
DEV_ASSERT((unsigned int)p_axis < 4);
return coord[p_axis];
}
@@ -91,17 +92,17 @@ struct [[nodiscard]] Vector4i {
_FORCE_INLINE_ int64_t length_squared() const;
_FORCE_INLINE_ double length() const;
_FORCE_INLINE_ void zero();
_FORCE_INLINE_ double distance_to(const Vector4i &p_to) const;
_FORCE_INLINE_ int64_t distance_squared_to(const Vector4i &p_to) const;
_FORCE_INLINE_ double distance_to(const Vector4i &p_to) const;
_FORCE_INLINE_ void zero();
_FORCE_INLINE_ Vector4i abs() const;
_FORCE_INLINE_ Vector4i sign() const;
Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const;
Vector4i clampi(int32_t p_min, int32_t p_max) const;
Vector4i snapped(const Vector4i &p_step) const;
Vector4i snappedi(int32_t p_step) const;
Vector4i clamp(const Vector4i &p_min, const Vector4i &p_max) const;
Vector4i clampi(int32_t p_min, int32_t p_max) const;
/* Operators */
@@ -116,12 +117,12 @@ struct [[nodiscard]] Vector4i {
_FORCE_INLINE_ Vector4i &operator%=(const Vector4i &p_v);
_FORCE_INLINE_ Vector4i operator%(const Vector4i &p_v) const;
_FORCE_INLINE_ Vector4i &operator*=(int32_t p_scalar);
_FORCE_INLINE_ Vector4i operator*(int32_t p_scalar) const;
_FORCE_INLINE_ Vector4i &operator/=(int32_t p_scalar);
_FORCE_INLINE_ Vector4i operator/(int32_t p_scalar) const;
_FORCE_INLINE_ Vector4i &operator%=(int32_t p_scalar);
_FORCE_INLINE_ Vector4i operator%(int32_t p_scalar) const;
_FORCE_INLINE_ Vector4i &operator*=(const int32_t p_scalar);
_FORCE_INLINE_ Vector4i operator*(const int32_t p_scalar) const;
_FORCE_INLINE_ Vector4i &operator/=(const int32_t p_scalar);
_FORCE_INLINE_ Vector4i operator/(const int32_t p_scalar) const;
_FORCE_INLINE_ Vector4i &operator%=(const int32_t p_scalar);
_FORCE_INLINE_ Vector4i operator%(const int32_t p_scalar) const;
_FORCE_INLINE_ Vector4i operator-() const;
@@ -137,7 +138,7 @@ struct [[nodiscard]] Vector4i {
_FORCE_INLINE_ Vector4i() {}
Vector4i(const Vector4 &p_vec4);
_FORCE_INLINE_ Vector4i(int32_t p_x, int32_t p_y, int32_t p_z, int32_t p_w) {
_FORCE_INLINE_ Vector4i(const int32_t p_x, const int32_t p_y, const int32_t p_z, const int32_t p_w) {
x = p_x;
y = p_y;
z = p_z;
@@ -153,20 +154,20 @@ double Vector4i::length() const {
return Math::sqrt((double)length_squared());
}
double Vector4i::distance_to(const Vector4i &p_to) const {
return (p_to - *this).length();
}
int64_t Vector4i::distance_squared_to(const Vector4i &p_to) const {
return (p_to - *this).length_squared();
}
double Vector4i::distance_to(const Vector4i &p_to) const {
return (p_to - *this).length();
}
Vector4i Vector4i::abs() const {
return Vector4i(Math::abs(x), Math::abs(y), Math::abs(z), Math::abs(w));
}
Vector4i Vector4i::sign() const {
return Vector4i(SIGN(x), SIGN(y), SIGN(z), SIGN(w));
return Vector4i(Math::sign(x), Math::sign(y), Math::sign(z), Math::sign(w));
}
/* Operators */
@@ -231,7 +232,7 @@ Vector4i Vector4i::operator%(const Vector4i &p_v) const {
return Vector4i(x % p_v.x, y % p_v.y, z % p_v.z, w % p_v.w);
}
Vector4i &Vector4i::operator*=(int32_t p_scalar) {
Vector4i &Vector4i::operator*=(const int32_t p_scalar) {
x *= p_scalar;
y *= p_scalar;
z *= p_scalar;
@@ -239,29 +240,29 @@ Vector4i &Vector4i::operator*=(int32_t p_scalar) {
return *this;
}
Vector4i Vector4i::operator*(int32_t p_scalar) const {
Vector4i Vector4i::operator*(const int32_t p_scalar) const {
return Vector4i(x * p_scalar, y * p_scalar, z * p_scalar, w * p_scalar);
}
// Multiplication operators required to workaround issues with LLVM using implicit conversion.
_FORCE_INLINE_ Vector4i operator*(int32_t p_scalar, const Vector4i &p_vector) {
_FORCE_INLINE_ Vector4i operator*(const int32_t p_scalar, const Vector4i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector4i operator*(int64_t p_scalar, const Vector4i &p_vector) {
_FORCE_INLINE_ Vector4i operator*(const int64_t p_scalar, const Vector4i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector4i operator*(float p_scalar, const Vector4i &p_vector) {
_FORCE_INLINE_ Vector4i operator*(const float p_scalar, const Vector4i &p_vector) {
return p_vector * p_scalar;
}
_FORCE_INLINE_ Vector4i operator*(double p_scalar, const Vector4i &p_vector) {
_FORCE_INLINE_ Vector4i operator*(const double p_scalar, const Vector4i &p_vector) {
return p_vector * p_scalar;
}
Vector4i &Vector4i::operator/=(int32_t p_scalar) {
Vector4i &Vector4i::operator/=(const int32_t p_scalar) {
x /= p_scalar;
y /= p_scalar;
z /= p_scalar;
@@ -269,11 +270,11 @@ Vector4i &Vector4i::operator/=(int32_t p_scalar) {
return *this;
}
Vector4i Vector4i::operator/(int32_t p_scalar) const {
Vector4i Vector4i::operator/(const int32_t p_scalar) const {
return Vector4i(x / p_scalar, y / p_scalar, z / p_scalar, w / p_scalar);
}
Vector4i &Vector4i::operator%=(int32_t p_scalar) {
Vector4i &Vector4i::operator%=(const int32_t p_scalar) {
x %= p_scalar;
y %= p_scalar;
z %= p_scalar;
@@ -281,7 +282,7 @@ Vector4i &Vector4i::operator%=(int32_t p_scalar) {
return *this;
}
Vector4i Vector4i::operator%(int32_t p_scalar) const {
Vector4i Vector4i::operator%(const int32_t p_scalar) const {
return Vector4i(x % p_scalar, y % p_scalar, z % p_scalar, w % p_scalar);
}
@@ -366,3 +367,5 @@ void Vector4i::zero() {
}
} // namespace godot
#endif // GODOT_VECTOR4I_HPP

View File

@@ -2,82 +2,121 @@
# -*- coding: utf-8 -*-
import sys
from pathlib import Path
if len(sys.argv) < 2:
print("Invalid usage of header_guards.py, it should be called with a path to one or multiple files.")
sys.exit(1)
HEADER_CHECK_OFFSET = 30
HEADER_BEGIN_OFFSET = 31
HEADER_END_OFFSET = -1
changed = []
invalid = []
for file in sys.argv[1:]:
header_start = -1
header_end = -1
with open(file.strip(), "rt", encoding="utf-8", newline="\n") as f:
with open(file, "rt", encoding="utf-8", newline="\n") as f:
lines = f.readlines()
for idx, line in enumerate(lines):
sline = line.strip()
if len(lines) <= HEADER_BEGIN_OFFSET:
continue # Most likely a dummy file.
if header_start < 0:
if sline == "": # Skip empty lines at the top.
continue
if lines[HEADER_CHECK_OFFSET].startswith("#import"):
continue # Early catch obj-c file.
if sline.startswith("/**********"): # Godot header starts this way.
header_start = idx
else:
header_end = 0 # There is no Godot header.
break
else:
if not sline.startswith(("*", "/*")): # Not in the Godot header anymore.
header_end = idx + 1 # The guard should be two lines below the Godot header.
break
name = f"GODOT_{Path(file).name}".upper().replace(".", "_").replace("-", "_").replace(" ", "_")
if (HEADER_CHECK_OFFSET := header_end) < 0 or HEADER_CHECK_OFFSET >= len(lines):
invalid.append(file)
continue
if lines[HEADER_CHECK_OFFSET].startswith("#pragma once"):
continue
# Might be using legacy header guards.
HEADER_BEGIN_OFFSET = HEADER_CHECK_OFFSET + 1
HEADER_END_OFFSET = len(lines) - 1
if HEADER_BEGIN_OFFSET >= HEADER_END_OFFSET:
invalid.append(file)
HEADER_CHECK = f"#ifndef {name}\n"
HEADER_BEGIN = f"#define {name}\n"
HEADER_END = f"#endif // {name}\n"
if (
lines[HEADER_CHECK_OFFSET] == HEADER_CHECK
and lines[HEADER_BEGIN_OFFSET] == HEADER_BEGIN
and lines[HEADER_END_OFFSET] == HEADER_END
):
continue
# Guards might exist but with the wrong names.
if (
lines[HEADER_CHECK_OFFSET].startswith("#ifndef")
and lines[HEADER_BEGIN_OFFSET].startswith("#define")
and lines[HEADER_END_OFFSET].startswith("#endif")
):
lines[HEADER_CHECK_OFFSET] = "#pragma once"
lines[HEADER_BEGIN_OFFSET] = "\n"
lines.pop()
lines[HEADER_CHECK_OFFSET] = HEADER_CHECK
lines[HEADER_BEGIN_OFFSET] = HEADER_BEGIN
lines[HEADER_END_OFFSET] = HEADER_END
with open(file, "wt", encoding="utf-8", newline="\n") as f:
f.writelines(lines)
changed.append(file)
continue
# Verify `#pragma once` doesn't exist at invalid location.
misplaced = False
for line in lines:
if line.startswith("#pragma once"):
misplaced = True
header_check = -1
header_begin = -1
header_end = -1
pragma_once = -1
objc = False
for idx, line in enumerate(lines):
if not line.startswith("#"):
continue
elif line.startswith("#ifndef") and header_check == -1:
header_check = idx
elif line.startswith("#define") and header_begin == -1:
header_begin = idx
elif line.startswith("#endif") and header_end == -1:
header_end = idx
elif line.startswith("#pragma once"):
pragma_once = idx
break
elif line.startswith("#import"):
objc = True
break
if misplaced:
invalid.append(file)
if objc:
continue
# Assume that we're simply missing a guard entirely.
lines.insert(HEADER_CHECK_OFFSET, "#pragma once\n\n")
with open(file, "wt", encoding="utf-8", newline="\n") as f:
f.writelines(lines)
changed.append(file)
if pragma_once != -1:
lines.pop(pragma_once)
lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK)
lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN)
lines.append("\n")
lines.append(HEADER_END)
with open(file, "wt", encoding="utf-8", newline="\n") as f:
f.writelines(lines)
changed.append(file)
continue
if header_check == -1 and header_begin == -1 and header_end == -1:
# Guards simply didn't exist
lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK)
lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN)
lines.append("\n")
lines.append(HEADER_END)
with open(file, "wt", encoding="utf-8", newline="\n") as f:
f.writelines(lines)
changed.append(file)
continue
if header_check != -1 and header_begin != -1 and header_end != -1:
# All prepends "found", see if we can salvage this.
if header_check == header_begin - 1 and header_begin < header_end:
lines.pop(header_check)
lines.pop(header_begin - 1)
lines.pop(header_end - 2)
if lines[header_end - 3] == "\n":
lines.pop(header_end - 3)
lines.insert(HEADER_CHECK_OFFSET, HEADER_CHECK)
lines.insert(HEADER_BEGIN_OFFSET, HEADER_BEGIN)
lines.append("\n")
lines.append(HEADER_END)
with open(file, "wt", encoding="utf-8", newline="\n") as f:
f.writelines(lines)
changed.append(file)
continue
invalid.append(file)
if changed:
for file in changed:

View File

@@ -5,16 +5,16 @@ ignore_missing_imports = true
namespace_packages = true
no_implicit_optional = true
pretty = true
scripts_are_modules = true
show_column_numbers = true
warn_redundant_casts = true
warn_return_any = true
warn_unreachable = true
python_version = "3.8"
[tool.ruff]
extend-include = ["*SConstruct"]
extend-include = ["SConstruct"]
line-length = 120
target-version = "py38"
target-version = "py37"
[tool.ruff.lint]
extend-select = [
@@ -27,32 +27,32 @@ extend-select = [
]
[tool.codespell]
enable-colors = true
write-changes = true
check-hidden = true
enable-colors = ""
write-changes = ""
check-hidden = ""
quiet-level = 3
builtin = ["clear", "rare", "en-GB_to_en-US"]
ignore-words-list = [
"breaked",
"cancelled",
"checkin",
"curvelinear",
"doubleclick",
"expct",
"findn",
"gird",
"hel",
"inout",
"labelin",
"lod",
"mis",
"nd",
"numer",
"ot",
"outin",
"requestor",
"te",
"textin",
"thirdparty",
"vai",
]
builtin = "clear,rare,en-GB_to_en-US"
ignore-words-list = """\
breaked,
cancelled,
checkin,
curvelinear,
doubleclick,
expct,
findn,
gird,
hel,
inout,
labelin,
lod,
mis,
nd,
numer,
ot,
outin,
requestor,
te,
textin,
thirdparty,
vai
"""

View File

@@ -60,13 +60,13 @@ void Wrapped::_postinitialize() {
Wrapped::_constructing_mutex.unlock();
#endif
Object *obj = dynamic_cast<Object *>(this);
if (obj) {
obj->notification(Object::NOTIFICATION_POSTINITIALIZE);
// Only send NOTIFICATION_POSTINITIALIZE for extension classes.
if (_is_extension_class()) {
_notificationv(Object::NOTIFICATION_POSTINITIALIZE);
}
}
Wrapped::Wrapped(const StringName &p_godot_class) {
Wrapped::Wrapped(const StringName p_godot_class) {
#ifdef HOT_RELOAD_ENABLED
if (unlikely(Wrapped::_constructing_recreate_owner)) {
_owner = Wrapped::_constructing_recreate_owner;
@@ -74,7 +74,7 @@ Wrapped::Wrapped(const StringName &p_godot_class) {
} else
#endif
{
_owner = godot::internal::gdextension_interface_classdb_construct_object2(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
_owner = godot::internal::gdextension_interface_classdb_construct_object(reinterpret_cast<GDExtensionConstStringNamePtr>(p_godot_class._native_ptr()));
}
if (_constructing_extension_class_name) {

Some files were not shown because too many files have changed in this diff Show More