diff --git a/.clang-format b/.clang-format index 1df6c35..87731d9 100644 --- a/.clang-format +++ b/.clang-format @@ -1,80 +1,105 @@ # 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 14.0). ---- -### General config, applies to all languages ### -BasedOnStyle: LLVM +# chosen value in case the base style changes (last sync: Clang 17.0.6). +BasedOnStyle: LLVM AccessModifierOffset: -4 AlignAfterOpenBracket: DontAlign # AlignArrayOfStructures: None -# AlignConsecutiveMacros: None -# AlignConsecutiveAssignments: None -# AlignConsecutiveBitFields: None -# AlignConsecutiveDeclarations: 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 # AlignEscapedNewlines: Right -AlignOperands: DontAlign -AlignTrailingComments: false +AlignOperands: DontAlign +AlignTrailingComments: + Kind: Never + OverEmptyLines: 0 # AllowAllArgumentsOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: false -# AllowShortEnumsOnASingleLine: true # AllowShortBlocksOnASingleLine: Never # AllowShortCaseLabelsOnASingleLine: false -# AllowShortFunctionsOnASingleLine: All -# AllowShortLambdasOnASingleLine: All +# AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Inline # AllowShortIfStatementsOnASingleLine: Never +# AllowShortLambdasOnASingleLine: All # AllowShortLoopsOnASingleLine: false # AlwaysBreakAfterDefinitionReturnType: None # AlwaysBreakAfterReturnType: None # AlwaysBreakBeforeMultilineStrings: false # AlwaysBreakTemplateDeclarations: MultiLine -# AttributeMacros: -# - __capability +AttributeMacros: + - _ALWAYS_INLINE_ + - _FORCE_INLINE_ + - _NO_INLINE_ # 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 -# BreakBeforeInheritanceComma: false -# BreakInheritanceList: BeforeColon +# BreakBeforeConceptDeclarations: Always +# BreakBeforeInlineASMColon: OnlyMultiline # BreakBeforeTernaryOperators: true -# BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: AfterColon +# BreakInheritanceList: BeforeColon # BreakStringLiterals: true -ColumnLimit: 0 -# CommentPragmas: '^ IWYU pragma:' -# QualifierAlignment: Leave +ColumnLimit: 0 +# CommentPragmas: "^ IWYU pragma:" # 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 @@ -82,34 +107,61 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: true # - 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 -IndentCaseLabels: true # IndentCaseBlocks: false +IndentCaseLabels: true +# IndentExternBlock: AfterExternBlock # IndentGotoLabels: true # IndentPPDirectives: None -# IndentExternBlock: AfterExternBlock -# IndentRequires: false -IndentWidth: 4 +# IndentRequiresClause: true +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 -# MacroBlockBegin: '' -# MacroBlockEnd: '' +# Language: Cpp +# LineEnding: DeriveLF +# 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 @@ -118,82 +170,71 @@ KeepEmptyLinesAtTheStartOfBlocks: false # PenaltyBreakString: 1000 # PenaltyBreakTemplateDeclaration: 10 # PenaltyExcessCharacter: 1000000 -# PenaltyReturnTypeOnItsOwnLine: 60 # PenaltyIndentedWhitespace: 0 +# PenaltyReturnTypeOnItsOwnLine: 60 # PointerAlignment: Right -# PPIndentWidth: -1 +# QualifierAlignment: Leave # 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: true +# SortUsingDeclarations: LexicographicNumeric # 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 -# AfterFunctionDefinitionName: false # AfterFunctionDeclarationName: false -# AfterIfMacros: true +# AfterFunctionDefinitionName: 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 -# SpacesInConditionalStatement: false +# SpacesInAngles: Never # 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 - Maximum: -1 -# SpacesInParentheses: false + 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 # SpacesInSquareBrackets: false -# SpaceBeforeSquareBrackets: false -# BitFieldColonSpacing: Both +Standard: c++20 # StatementAttributeLikeMacros: # - Q_EMIT # StatementMacros: # - Q_UNUSED # - QT_REQUIRE_VERSION -TabWidth: 4 -# UseCRLF: false -UseTab: Always +TabWidth: 4 +UseTab: Always +# VerilogBreakBetweenInstancePorts: true # WhitespaceSensitiveMacros: -# - 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'] -... +# - NS_SWIFT_NAME +# - PP_STRINGIZE +# - STRINGIZE diff --git a/.editorconfig b/.editorconfig index f14ac7f..0da03e8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,11 +6,12 @@ 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}] +[{*.{yml,yaml},.clang-format}] indent_size = 2 indent_style = space diff --git a/.github/actions/setup-godot-cpp/action.yml b/.github/actions/setup-godot-cpp/action.yml index 1be9293..d67bb99 100644 --- a/.github/actions/setup-godot-cpp/action.yml +++ b/.github/actions/setup-godot-cpp/action.yml @@ -20,7 +20,7 @@ inputs: default: 12.2.0 description: MinGW version. ndk-version: - default: r23c + default: r28b description: Android NDK version. buildtool: default: scons diff --git a/.github/workflows/ci-cmake.yml b/.github/workflows/ci-cmake.yml index b39fba9..304a88f 100644 --- a/.github/workflows/ci-cmake.yml +++ b/.github/workflows/ci-cmake.yml @@ -40,17 +40,8 @@ jobs: artifact-path: cmake-build/bin/libgodot-cpp.linux.template_release.x86_64.a run-tests: true - - name: 🐧 Linux (GCC, Makefiles, Double Precision) - os: ubuntu-22.04 - platform: linux - config-flags: -DCMAKE_BUILD_TYPE=Release -DGODOTCPP_PRECISION=double - artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release.cmake - artifact-path: cmake-build/bin/libgodot-cpp.linux.template_release.double.x86_64.a - flags: precision=double - run-tests: false - - name: 🏁 Windows (x86_64, MSVC) - os: windows-2019 + os: windows-2022 platform: windows compiler: msvc build-flags: --config Release @@ -59,7 +50,7 @@ jobs: run-tests: false - name: 🏁 Windows (x86_64, MinGW, Ninja) - os: windows-2019 + os: windows-2022 platform: windows compiler: mingw config-flags: @@ -82,8 +73,8 @@ jobs: platform: android config-flags: -G Ninja -DCMAKE_BUILD_TYPE=Release - --toolchain ${ANDROID_HOME}/ndk/23.2.8568313/build/cmake/android.toolchain.cmake - -DANDROID_PLATFORM=21 -DANDROID_ABI=arm64-v8a + --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 diff --git a/.github/workflows/ci-scons.yml b/.github/workflows/ci-scons.yml index d151aec..447598d 100644 --- a/.github/workflows/ci-scons.yml +++ b/.github/workflows/ci-scons.yml @@ -10,6 +10,8 @@ env: # Use UTF-8 on Linux. LANG: en_US.UTF-8 LC_ALL: en_US.UTF-8 + # Use UTF-8 on Windows. + PYTHONIOENCODING: utf8 concurrency: group: ci-scons-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }} @@ -31,17 +33,8 @@ jobs: run-tests: true cache-name: linux-x86_64 - - name: 🐧 Linux (GCC, Double Precision) - os: ubuntu-22.04 - platform: linux - artifact-name: redot-cpp-linux-glibc2.27-x86_64-double-release - artifact-path: bin/libredot-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-2019 + os: windows-2022 platform: windows artifact-name: redot-cpp-windows-msvc2019-x86_64-release artifact-path: bin/libredot-cpp.windows.template_release.x86_64.lib @@ -49,7 +42,7 @@ jobs: cache-name: windows-x86_64-msvc - name: 🏁 Windows (x86_64, MinGW) - os: windows-2019 + os: windows-2022 platform: windows artifact-name: redot-cpp-linux-mingw-x86_64-release artifact-path: bin/libredot-cpp.windows.template_release.x86_64.a diff --git a/.github/workflows/runner.yml b/.github/workflows/runner.yml index d056236..62f9327 100644 --- a/.github/workflows/runner.yml +++ b/.github/workflows/runner.yml @@ -34,13 +34,14 @@ jobs: - '.github/workflows/*.yml' - '**/*.py' - '**/*.cpp' + - '**/*.hpp' - '**/*.h' + - '**/*.inc' - 'test/build_profile.json' - 'gdextension/extension_api.json' scons: - '**/SConstruct' - '**/SCsub' - - '**/*.py' cmake: - '**/CMakeLists.txt' - '**/*.cmake' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7354ba4..e370058 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,32 +9,36 @@ exclude: | repos: - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v17.0.6 + rev: v20.1.0 hooks: - id: clang-format - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.4 + rev: v0.11.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: v0.971 + rev: v1.14.1 # Latest version that supports Python 3.8 hooks: - id: mypy files: \.py$ types_or: [text] - repo: https://github.com/codespell-project/codespell - rev: v2.3.0 + rev: v2.4.1 hooks: - id: codespell additional_dependencies: [tomli] - repo: https://github.com/BlankSpruce/gersemi - rev: 0.18.2 + rev: 0.19.2 hooks: - id: gersemi args: ["-i", "--no-warn-about-unknown-commands", "-l", "120"] diff --git a/README.md b/README.md index bf42630..0ac86fe 100644 --- a/README.md +++ b/README.md @@ -37,22 +37,15 @@ Redot version.** ## Compatibility -> [!WARNING] -> -> The GDExtension API is brand new since Godot 4.0, and is still -considered in **beta** stage, despite Redot 4.3 itself being released. -> -> This applies to both the GDExtension interface header, the API JSON, and this -first-party `redot-cpp` extension. -> -> Some compatibility breakage is to be expected as GDExtension and `redot-cpp` -> get more used, documented, and critical issues get resolved. See the -> [Redot issue tracker](https://github.com/Redot-Engine/redot-engine/issues?q=is%3Aissue+is%3Aopen+label%3Atopic%3Agdextension), -> the [Godot issue tracker](ttps://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3Atopic%3Agdextension), -> the [godot-cpp issue tracker](https://github.com/godotengine/godot-cpp/issues), -> and the [redot-cpp issue tracker](https://github.com/Redot-Engine/redot-cpp/issues) -> for a list of known issues, and be sure to provide feedback on issues and PRs -> which affect your use of this extension. +GDExtensions targeting an earlier version of Redot or Godot should work in later minor versions, +but not vice-versa. For example, a GDExtension targeting Godot 4.2 should work just fine +in Redot/Godot 4.3, but one targeting Redot/Godot 4.3 won't work in Godot 4.2. + +There is one exception to this: extensions targeting Godot 4.0 will _not_ work with +Godot 4.1 and later. +See [Updating your GDExtension for 4.1](https://docs.godotengine.org/en/latest/tutorials/migrating/upgrading_to_godot_4.1.html#updating-your-gdextension-for-godot-4-1). + +GDExtensions targeting any Redot version may not run on any Godot version. ## Contributing diff --git a/SConstruct b/SConstruct index 8acea26..3ebdff9 100644 --- a/SConstruct +++ b/SConstruct @@ -1,9 +1,14 @@ #!/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) +EnsureSConsVersion(4, 0) +EnsurePythonVersion(3, 8) try: Import("env") @@ -27,7 +32,7 @@ if profile: elif os.path.isfile(profile + ".py"): customs.append(profile + ".py") opts = Variables(customs, ARGUMENTS) -cpp_tool = Tool("godotcpp", toolpath=["tools"]) +cpp_tool = Tool("godotcpp", toolpath=[Dir("tools").srcnode().abspath]) cpp_tool.options(opts, env) opts.Update(env) diff --git a/binding_generator.py b/binding_generator.py index 216f0a2..152396a 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -356,7 +356,7 @@ def generate_builtin_bindings(api, output_dir, build_config): add_header("variant_size.hpp", variant_size_source) variant_size_source.append("#pragma once") - variant_size_source.append(f'#define GODOT_CPP_VARIANT_SIZE {builtin_sizes["Variant"]}') + variant_size_source.append(f"#define GODOT_CPP_VARIANT_SIZE {builtin_sizes['Variant']}") variant_size_file.write("\n".join(variant_size_source)) @@ -601,19 +601,19 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl if "constructors" in builtin_api: for constructor in builtin_api["constructors"]: - result.append(f'\t\tGDExtensionPtrConstructor constructor_{constructor["index"]};') + result.append(f"\t\tGDExtensionPtrConstructor constructor_{constructor['index']};") if builtin_api["has_destructor"]: result.append("\t\tGDExtensionPtrDestructor destructor;") if "methods" in builtin_api: for method in builtin_api["methods"]: - result.append(f'\t\tGDExtensionPtrBuiltInMethod method_{method["name"]};') + result.append(f"\t\tGDExtensionPtrBuiltInMethod method_{method['name']};") if "members" in builtin_api: for member in builtin_api["members"]: - result.append(f'\t\tGDExtensionPtrSetter member_{member["name"]}_setter;') - result.append(f'\t\tGDExtensionPtrGetter member_{member["name"]}_getter;') + result.append(f"\t\tGDExtensionPtrSetter member_{member['name']}_setter;") + result.append(f"\t\tGDExtensionPtrGetter member_{member['name']}_getter;") if "indexing_return_type" in builtin_api: result.append("\t\tGDExtensionPtrIndexedSetter indexed_setter;") @@ -628,10 +628,10 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl for operator in builtin_api["operators"]: if "right_type" in operator: result.append( - f'\t\tGDExtensionPtrOperatorEvaluator operator_{get_operator_id_name(operator["name"])}_{operator["right_type"]};' + f"\t\tGDExtensionPtrOperatorEvaluator operator_{get_operator_id_name(operator['name'])}_{operator['right_type']};" ) else: - result.append(f'\t\tGDExtensionPtrOperatorEvaluator operator_{get_operator_id_name(operator["name"])};') + result.append(f"\t\tGDExtensionPtrOperatorEvaluator operator_{get_operator_id_name(operator['name'])};") result.append("\t} _method_bindings;") @@ -693,12 +693,12 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl if class_name == "Vector3" and constant["name"].startswith("AXIS"): if axis_constants_count == 0: result.append("\tenum Axis {") - result.append(f'\t\t{constant["name"]} = {constant["value"]},') + result.append(f"\t\t{constant['name']} = {constant['value']},") axis_constants_count += 1 if axis_constants_count == 3: result.append("\t};") else: - result.append(f'\tstatic const {correct_type(constant["type"])} {constant["name"]};') + result.append(f"\tstatic const {correct_type(constant['type'])} {constant['name']};") if builtin_api["has_destructor"]: result.append(f"\t~{class_name}();") @@ -718,13 +718,13 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl method_signature += "static " if "return_type" in method: - method_signature += f'{correct_type(method["return_type"])}' + method_signature += f"{correct_type(method['return_type'])}" if not method_signature.endswith("*"): method_signature += " " else: method_signature += "void " - method_signature += f'{method["name"]}(' + method_signature += f"{method['name']}(" method_arguments = [] if "arguments" in method: @@ -759,21 +759,21 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl if "members" in builtin_api: for member in builtin_api["members"]: - if f'get_{member["name"]}' not in method_list: - result.append(f'\t{correct_type(member["type"])} get_{member["name"]}() const;') - if f'set_{member["name"]}' not in method_list: - result.append(f'\tvoid set_{member["name"]}({type_for_parameter(member["type"])}value);') + if f"get_{member['name']}" not in method_list: + result.append(f"\t{correct_type(member['type'])} get_{member['name']}() const;") + if f"set_{member['name']}" not in method_list: + result.append(f"\tvoid set_{member['name']}({type_for_parameter(member['type'])}value);") if "operators" in builtin_api: for operator in builtin_api["operators"]: if is_valid_cpp_operator(operator["name"]): if "right_type" in operator: result.append( - f'\t{correct_type(operator["return_type"])} operator{get_operator_cpp_name(operator["name"])}({type_for_parameter(operator["right_type"])}p_other) const;' + f"\t{correct_type(operator['return_type'])} operator{get_operator_cpp_name(operator['name'])}({type_for_parameter(operator['right_type'])}p_other) const;" ) else: result.append( - f'\t{correct_type(operator["return_type"])} operator{get_operator_cpp_name(operator["name"])}() const;' + f"\t{correct_type(operator['return_type'])} operator{get_operator_cpp_name(operator['name'])}() const;" ) # Copy assignment. @@ -911,7 +911,6 @@ def generate_builtin_class_header(builtin_api, size, used_classes, fully_used_cl result.append("\tconst Variant &operator[](int64_t p_index) const;") result.append("\tVariant &operator[](int64_t p_index);") result.append("\tvoid set_typed(uint32_t p_type, const StringName &p_class_name, const Variant &p_script);") - result.append("\tvoid _ref(const Array &p_from) const;") result.append(""" struct Iterator { _FORCE_INLINE_ Variant &operator*() const; @@ -1041,7 +1040,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl if "constructors" in builtin_api: for constructor in builtin_api["constructors"]: result.append( - f'\t_method_bindings.constructor_{constructor["index"]} = internal::gdextension_interface_variant_get_ptr_constructor({enum_type_name}, {constructor["index"]});' + f"\t_method_bindings.constructor_{constructor['index']} = internal::gdextension_interface_variant_get_ptr_constructor({enum_type_name}, {constructor['index']});" ) if builtin_api["has_destructor"]: @@ -1065,17 +1064,17 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl # TODO: Add error check for hash mismatch. result.append(f'\t_gde_name = StringName("{method["name"]}");') result.append( - f'\t_method_bindings.method_{method["name"]} = internal::gdextension_interface_variant_get_ptr_builtin_method({enum_type_name}, _gde_name._native_ptr(), {method["hash"]});' + f"\t_method_bindings.method_{method['name']} = internal::gdextension_interface_variant_get_ptr_builtin_method({enum_type_name}, _gde_name._native_ptr(), {method['hash']});" ) if "members" in builtin_api: for member in builtin_api["members"]: result.append(f'\t_gde_name = StringName("{member["name"]}");') result.append( - f'\t_method_bindings.member_{member["name"]}_setter = internal::gdextension_interface_variant_get_ptr_setter({enum_type_name}, _gde_name._native_ptr());' + f"\t_method_bindings.member_{member['name']}_setter = internal::gdextension_interface_variant_get_ptr_setter({enum_type_name}, _gde_name._native_ptr());" ) result.append( - f'\t_method_bindings.member_{member["name"]}_getter = internal::gdextension_interface_variant_get_ptr_getter({enum_type_name}, _gde_name._native_ptr());' + f"\t_method_bindings.member_{member['name']}_getter = internal::gdextension_interface_variant_get_ptr_getter({enum_type_name}, _gde_name._native_ptr());" ) if "indexing_return_type" in builtin_api: @@ -1107,11 +1106,11 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl f"GDEXTENSION_VARIANT_TYPE_{camel_to_snake(operator['right_type']).upper()}" ) result.append( - f'\t_method_bindings.operator_{get_operator_id_name(operator["name"])}_{operator["right_type"]} = internal::gdextension_interface_variant_get_ptr_operator_evaluator(GDEXTENSION_VARIANT_OP_{get_operator_id_name(operator["name"]).upper()}, {enum_type_name}, {right_type_variant_type});' + f"\t_method_bindings.operator_{get_operator_id_name(operator['name'])}_{operator['right_type']} = internal::gdextension_interface_variant_get_ptr_operator_evaluator(GDEXTENSION_VARIANT_OP_{get_operator_id_name(operator['name']).upper()}, {enum_type_name}, {right_type_variant_type});" ) else: result.append( - f'\t_method_bindings.operator_{get_operator_id_name(operator["name"])} = internal::gdextension_interface_variant_get_ptr_operator_evaluator(GDEXTENSION_VARIANT_OP_{get_operator_id_name(operator["name"]).upper()}, {enum_type_name}, GDEXTENSION_VARIANT_TYPE_NIL);' + f"\t_method_bindings.operator_{get_operator_id_name(operator['name'])} = internal::gdextension_interface_variant_get_ptr_operator_evaluator(GDEXTENSION_VARIANT_OP_{get_operator_id_name(operator['name']).upper()}, {enum_type_name}, GDEXTENSION_VARIANT_TYPE_NIL);" ) result.append("}") @@ -1136,7 +1135,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl result.append(method_signature) method_call = ( - f'\tinternal::_call_builtin_constructor(_method_bindings.constructor_{constructor["index"]}, &opaque' + f"\tinternal::_call_builtin_constructor(_method_bindings.constructor_{constructor['index']}, &opaque" ) if "arguments" in constructor: if len(constructor["arguments"]) == 1 and constructor["arguments"][0]["type"] == class_name: @@ -1204,7 +1203,7 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl method_call += f"return internal::_call_builtin_method_ptr_ret_obj<{return_type}>(" else: method_call += "internal::_call_builtin_method_ptr_no_ret(" - method_call += f'_method_bindings.method_{method["name"]}, ' + method_call += f"_method_bindings.method_{method['name']}, " if "is_static" in method and method["is_static"]: method_call += "nullptr" else: @@ -1233,19 +1232,19 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl if "members" in builtin_api: for member in builtin_api["members"]: - if f'get_{member["name"]}' not in method_list: - result.append(f'{correct_type(member["type"])} {class_name}::get_{member["name"]}() const {{') + if f"get_{member['name']}" not in method_list: + result.append(f"{correct_type(member['type'])} {class_name}::get_{member['name']}() const {{") result.append( - f'\treturn internal::_call_builtin_ptr_getter<{correct_type(member["type"])}>(_method_bindings.member_{member["name"]}_getter, (GDExtensionConstTypePtr)&opaque);' + f"\treturn internal::_call_builtin_ptr_getter<{correct_type(member['type'])}>(_method_bindings.member_{member['name']}_getter, (GDExtensionConstTypePtr)&opaque);" ) result.append("}") - if f'set_{member["name"]}' not in method_list: - result.append(f'void {class_name}::set_{member["name"]}({type_for_parameter(member["type"])}value) {{') + if f"set_{member['name']}" not in method_list: + result.append(f"void {class_name}::set_{member['name']}({type_for_parameter(member['type'])}value) {{") (encode, arg_name) = get_encoded_arg("value", member["type"], None) result += encode result.append( - f'\t_method_bindings.member_{member["name"]}_setter((GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr){arg_name});' + f"\t_method_bindings.member_{member['name']}_setter((GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr){arg_name});" ) result.append("}") @@ -1256,20 +1255,20 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl if is_valid_cpp_operator(operator["name"]): if "right_type" in operator: result.append( - f'{correct_type(operator["return_type"])} {class_name}::operator{get_operator_cpp_name(operator["name"])}({type_for_parameter(operator["right_type"])}p_other) const {{' + f"{correct_type(operator['return_type'])} {class_name}::operator{get_operator_cpp_name(operator['name'])}({type_for_parameter(operator['right_type'])}p_other) const {{" ) (encode, arg_name) = get_encoded_arg("other", operator["right_type"], None) result += encode result.append( - f'\treturn internal::_call_builtin_operator_ptr<{get_gdextension_type(correct_type(operator["return_type"]))}>(_method_bindings.operator_{get_operator_id_name(operator["name"])}_{operator["right_type"]}, (GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr){arg_name});' + f"\treturn internal::_call_builtin_operator_ptr<{get_gdextension_type(correct_type(operator['return_type']))}>(_method_bindings.operator_{get_operator_id_name(operator['name'])}_{operator['right_type']}, (GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr){arg_name});" ) result.append("}") else: result.append( - f'{correct_type(operator["return_type"])} {class_name}::operator{get_operator_cpp_name(operator["name"])}() const {{' + f"{correct_type(operator['return_type'])} {class_name}::operator{get_operator_cpp_name(operator['name'])}() const {{" ) result.append( - f'\treturn internal::_call_builtin_operator_ptr<{get_gdextension_type(correct_type(operator["return_type"]))}>(_method_bindings.operator_{get_operator_id_name(operator["name"])}, (GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr) nullptr);' + f"\treturn internal::_call_builtin_operator_ptr<{get_gdextension_type(correct_type(operator['return_type']))}>(_method_bindings.operator_{get_operator_id_name(operator['name'])}, (GDExtensionConstTypePtr)&opaque, (GDExtensionConstTypePtr) nullptr);" ) result.append("}") result.append("") @@ -1638,12 +1637,12 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us if "enums" in class_api: for enum_api in class_api["enums"]: if enum_api["is_bitfield"]: - result.append(f'\tenum {enum_api["name"]} : uint64_t {{') + result.append(f"\tenum {enum_api['name']} : uint64_t {{") else: - result.append(f'\tenum {enum_api["name"]} {{') + result.append(f"\tenum {enum_api['name']} {{") for value in enum_api["values"]: - result.append(f'\t\t{value["name"]} = {value["value"]},') + result.append(f"\t\t{value['name']} = {value['value']},") result.append("\t};") result.append("") @@ -1651,7 +1650,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us for value in class_api["constants"]: if "type" not in value: value["type"] = "int" - result.append(f'\tstatic const {value["type"]} {value["name"]} = {value["value"]};') + result.append(f"\tstatic const {value['type']} {value['name']} = {value['value']};") result.append("") if is_singleton: @@ -1723,6 +1722,16 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append(f"\t~{class_name}();") result.append("") + if class_name == "Object": + result.append('\tString _to_string() const { return "<" + get_class() + "#" + itos(get_instance_id()) + ">"; }') + result.append("") + + if class_name == "Node": + result.append( + '\tString _to_string() const { return (!get_name().is_empty() ? String(get_name()) + ":" : "") + Object::_to_string(); }' + ) + result.append("") + result.append("public:") # Special cases. @@ -1774,9 +1783,9 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us if "enums" in class_api and class_name != "Object": for enum_api in class_api["enums"]: if enum_api["is_bitfield"]: - result.append(f'VARIANT_BITFIELD_CAST({class_name}::{enum_api["name"]});') + result.append(f"VARIANT_BITFIELD_CAST({class_name}::{enum_api['name']});") else: - result.append(f'VARIANT_ENUM_CAST({class_name}::{enum_api["name"]});') + result.append(f"VARIANT_ENUM_CAST({class_name}::{enum_api['name']});") result.append("") if class_name == "ClassDBSingleton": @@ -1785,12 +1794,12 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us if "enums" in class_api: for enum_api in class_api["enums"]: if enum_api["is_bitfield"]: - result.append(f'\tenum {enum_api["name"]} : uint64_t {{ \\') + result.append(f"\tenum {enum_api['name']} : uint64_t {{ \\") else: - result.append(f'\tenum {enum_api["name"]} {{ \\') + result.append(f"\tenum {enum_api['name']} {{ \\") for value in enum_api["values"]: - result.append(f'\t\t{value["name"]} = {value["value"]}, \\') + result.append(f"\t\t{value['name']} = {value['value']}, \\") result.append("\t}; \\") result.append("\t \\") @@ -1821,7 +1830,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us else: method_signature += "void " - method_signature += f'{method["name"]}(' + method_signature += f"{method['name']}(" method_arguments = [] if "arguments" in method: @@ -1840,7 +1849,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us method_body += "return " if "alias_for" in class_api and return_type.startswith(class_api["alias_for"] + "::"): method_body += f"({return_type})" - method_body += f'ClassDBSingleton::get_singleton()->{method["name"]}(' + method_body += f"ClassDBSingleton::get_singleton()->{method['name']}(" method_body += ", ".join(map(lambda x: escape_argument(x["name"]), method_arguments)) if vararg: method_body += ", p_args..." @@ -1856,9 +1865,9 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us if "enums" in class_api: for enum_api in class_api["enums"]: if enum_api["is_bitfield"]: - result.append(f'\tVARIANT_BITFIELD_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\') + result.append(f"\tVARIANT_BITFIELD_CAST({class_api['alias_for']}::{enum_api['name']}); \\") else: - result.append(f'\tVARIANT_ENUM_CAST({class_api["alias_for"]}::{enum_api["name"]}); \\') + result.append(f"\tVARIANT_ENUM_CAST({class_api['alias_for']}::{enum_api['name']}); \\") result.append("\t") result.append("") @@ -1955,7 +1964,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us if has_return: result.append( - f'\tCHECK_METHOD_BIND_RET(_gde_method_bind, ({get_default_value_for_type(method["return_value"]["type"])}));' + f"\tCHECK_METHOD_BIND_RET(_gde_method_bind, ({get_default_value_for_type(method['return_value']['type'])}));" ) else: result.append("\tCHECK_METHOD_BIND(_gde_method_bind);") @@ -2037,7 +2046,7 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us method_signature += " {" if "return_value" in method and correct_type(method["return_value"]["type"]) != "void": result.append(method_signature) - result.append(f'\treturn {get_default_value_for_type(method["return_value"]["type"])};') + result.append(f"\treturn {get_default_value_for_type(method['return_value']['type'])};") result.append("}") else: method_signature += "}" @@ -2073,7 +2082,7 @@ def generate_global_constants(api, output_dir): if len(api["global_constants"]) > 0: for constant in api["global_constants"]: - header.append(f'const int64_t {escape_identifier(constant["name"])} = {constant["value"]};') + header.append(f"const int64_t {escape_identifier(constant['name'])} = {constant['value']};") header.append("") @@ -2082,12 +2091,12 @@ def generate_global_constants(api, output_dir): continue if enum_def["is_bitfield"]: - header.append(f'enum {enum_def["name"]} : uint64_t {{') + header.append(f"enum {enum_def['name']} : uint64_t {{") else: - header.append(f'enum {enum_def["name"]} {{') + header.append(f"enum {enum_def['name']} {{") for value in enum_def["values"]: - header.append(f'\t{value["name"]} = {value["value"]},') + header.append(f"\t{value['name']} = {value['value']},") header.append("};") header.append("") @@ -2115,18 +2124,18 @@ def generate_version_header(api, output_dir): header.append(f"#define REDOT_VERSION_MAJOR {api['redot_header']['version_major']}") header.append(f"#define REDOT_VERSION_MINOR {api['redot_header']['version_minor']}") header.append(f"#define REDOT_VERSION_PATCH {api['redot_header']['version_patch']}") - header.append(f"#define REDOT_VERSION_STATUS \"{api['redot_header']['version_status']}\"") + header.append(f'#define REDOT_VERSION_STATUS "{api["redot_header"]["version_status"]}"') header.append(f"#define REDOT_VERSION_STATUS_VERSION {api['redot_header']['version_status_version']}") - header.append(f"#define REDOT_VERSION_BUILD \"{api['redot_header']['version_build']}\"") + header.append(f'#define REDOT_VERSION_BUILD "{api["redot_header"]["version_build"]}"') header.append(f"#define GODOT_VERSION_MAJOR {api['header']['version_major']}") header.append(f"#define GODOT_VERSION_MINOR {api['header']['version_minor']}") header.append(f"#define GODOT_VERSION_PATCH {api['header']['version_patch']}") - header.append(f"#define GODOT_VERSION_STATUS \"{api['header']['version_status']}\"") + header.append(f'#define GODOT_VERSION_STATUS "{api["header"]["version_status"]}"') header.append( f"#define GODOT_VERSION_STATUS_VERSION {next(filter(str.isdigit, api['header']['version_status']), 0)}" ) - header.append(f"#define GODOT_VERSION_BUILD \"{api['header']['version_build']}\"") + header.append(f'#define GODOT_VERSION_BUILD "{api["header"]["version_build"]}"') header.append("") @@ -2158,9 +2167,9 @@ def generate_global_constant_binds(api, output_dir): continue if enum_def["is_bitfield"]: - header.append(f'VARIANT_BITFIELD_CAST({enum_def["name"]});') + header.append(f"VARIANT_BITFIELD_CAST({enum_def['name']});") else: - header.append(f'VARIANT_ENUM_CAST({enum_def["name"]});') + header.append(f"VARIANT_ENUM_CAST({enum_def['name']});") # Variant::Type is not a global enum, but only one line, it is worth to place in this file instead of creating new file. header.append("VARIANT_ENUM_CAST(godot::Variant::Type);") @@ -2259,7 +2268,7 @@ def generate_utility_functions(api, output_dir): has_return = "return_type" in function and function["return_type"] != "void" if has_return: source.append( - f'\tCHECK_METHOD_BIND_RET(_gde_function, ({get_default_value_for_type(function["return_type"])}));' + f"\tCHECK_METHOD_BIND_RET(_gde_function, ({get_default_value_for_type(function['return_type'])}));" ) else: source.append("\tCHECK_METHOD_BIND(_gde_function);") @@ -2271,7 +2280,7 @@ def generate_utility_functions(api, output_dir): if function["return_type"] == "Object": function_call += "internal::_call_utility_ret_obj(_gde_function" else: - function_call += f'internal::_call_utility_ret<{get_gdextension_type(correct_type(function["return_type"]))}>(_gde_function' + function_call += f"internal::_call_utility_ret<{get_gdextension_type(correct_type(function['return_type']))}>(_gde_function" else: function_call += "internal::_call_utility_no_ret(_gde_function" @@ -2289,7 +2298,7 @@ def generate_utility_functions(api, output_dir): function_call += ", ".join(arguments) else: if has_return: - source.append(f'\t{get_gdextension_type(correct_type(function["return_type"]))} ret;') + source.append(f"\t{get_gdextension_type(correct_type(function['return_type']))} ret;") else: source.append("\tVariant ret;") function_call += "_gde_function(&ret, reinterpret_cast(p_args), p_arg_count" @@ -2483,7 +2492,7 @@ def make_varargs_template( if len(class_befor_signature) > 0: function_signature += class_befor_signature + "::" - function_signature += f'{escape_identifier(function_data["name"])}' + function_signature += f"{escape_identifier(function_data['name'])}" method_arguments = [] if "arguments" in function_data: @@ -2508,7 +2517,7 @@ def make_varargs_template( if argument["type"] == "Variant": args_array += escape_argument(argument["name"]) else: - args_array += f'Variant({escape_argument(argument["name"])})' + args_array += f"Variant({escape_argument(argument['name'])})" args_array += ", " args_array += "Variant(p_args)... }};" @@ -2524,7 +2533,7 @@ def make_varargs_template( if return_type != "void": call_line += "return " - call_line += f'{escape_identifier(function_data["name"])}_internal(call_args.data(), variant_args.size());' + call_line += f"{escape_identifier(function_data['name'])}_internal(call_args.data(), variant_args.size());" result.append(call_line) else: base = "(GDExtensionTypePtr)&opaque" @@ -2534,7 +2543,7 @@ def make_varargs_template( ret = "nullptr" if return_type != "void": ret = "&ret" - result.append(f'\t{correct_type(function_data["return_type"])} ret;') + result.append(f"\t{correct_type(function_data['return_type'])} ret;") function_name = function_data["name"] result.append( @@ -2755,9 +2764,22 @@ def correct_type(type_name, meta=None, use_alias=True): if type_name in type_conversion: return type_conversion[type_name] if type_name.startswith("typedarray::"): - return type_name.replace("typedarray::", "TypedArray<") + ">" + arr_type_name = type_name.replace("typedarray::", "") + if is_refcounted(arr_type_name): + arr_type_name = "Ref<" + arr_type_name + ">" + return "TypedArray<" + arr_type_name + ">" if type_name.startswith("typeddictionary::"): - return type_name.replace("typeddictionary::", "TypedDictionary<").replace(";", ", ") + ">" + dict_type_name = type_name.replace("typeddictionary::", "") + dict_type_names = dict_type_name.split(";") + if is_refcounted(dict_type_names[0]): + key_name = "Ref<" + dict_type_names[0] + ">" + else: + key_name = dict_type_names[0] + if is_refcounted(dict_type_names[1]): + val_name = "Ref<" + dict_type_names[1] + ">" + else: + val_name = dict_type_names[1] + return "TypedDictionary<" + key_name + ", " + val_name + ">" if is_enum(type_name): if is_bitfield(type_name): base_class = get_enum_class(type_name) diff --git a/cmake/GodotCPPModule.cmake b/cmake/GodotCPPModule.cmake index 00e00fe..67fc4dc 100644 --- a/cmake/GodotCPPModule.cmake +++ b/cmake/GodotCPPModule.cmake @@ -86,9 +86,9 @@ missing. ]] function( binding_generator_generate_bindings API_FILE - USE_TEMPLATE_GET_NODE, - BITS, - PRECISION, + USE_TEMPLATE_GET_NODE + BITS + PRECISION OUTPUT_DIR ) # This code snippet will be squashed into a single line diff --git a/cmake/android.cmake b/cmake/android.cmake index 1d3a93b..7c442bb 100644 --- a/cmake/android.cmake +++ b/cmake/android.cmake @@ -34,7 +34,7 @@ function(android_options) more information android_api_level : Target Android API level. - Default = 21 + Default = 24 ANDROID_HOME : Path to your Android SDK installation. Default = os.environ.get("ANDROID_HOME", os.environ.get("ANDROID_SDK_ROOT") diff --git a/cmake/common_compiler_flags.cmake b/cmake/common_compiler_flags.cmake index 9d4894f..8a9a41c 100644 --- a/cmake/common_compiler_flags.cmake +++ b/cmake/common_compiler_flags.cmake @@ -47,7 +47,7 @@ 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("Using clang-cl") + message(STATUS "Using clang-cl") set(IS_CLANG "0" PARENT_SCOPE) set(IS_MSVC "1" PARENT_SCOPE) set(NOT_MSVC "0" PARENT_SCOPE) diff --git a/cmake/godotcpp.cmake b/cmake/godotcpp.cmake index b932805..a0c544f 100644 --- a/cmake/godotcpp.cmake +++ b/cmake/godotcpp.cmake @@ -29,7 +29,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows.cmake) # Detect number of processors include(ProcessorCount) ProcessorCount(PROC_MAX) -message("Auto-detected ${PROC_MAX} CPU cores available for build parallelism.") +message(STATUS "Auto-detected ${PROC_MAX} CPU cores available for build parallelism.") # List of known platforms set(PLATFORM_LIST @@ -197,15 +197,21 @@ function(godotcpp_generate) another compiler simulating the Visual C++ cl command-line syntax. ]] if(MSVC) math(EXPR PROC_N "(${PROC_MAX}-1) | (${X}-2)>>31 & 1") - message("Using ${PROC_N} cores for multi-threaded compilation.") + 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}") + else() + set(_cores "all") + endif() message( - "Using ${CMAKE_BUILD_PARALLEL_LEVEL} cores, You can override" - " it at configure time by using -j or --parallel on the build" + STATUS + "Using ${_cores} cores. You can override" + " this at configure time by using -j or --parallel in the build" " command." ) - message(" eg. cmake --build . -j 7 ...") + message(STATUS " eg. cmake --build . -j 7 ...") endif() #[[ GODOTCPP_SYMBOL_VISIBLITY @@ -245,8 +251,8 @@ function(godotcpp_generate) # Build Profile if(GODOTCPP_BUILD_PROFILE) message(STATUS "Using build profile to trim api file") - message("\tBUILD_PROFILE = '${GODOTCPP_BUILD_PROFILE}'") - message("\tAPI_SOURCE = '${GODOTCPP_GDEXTENSION_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}" diff --git a/doc/cmake.rst b/doc/cmake.rst index 760d456..467ba0b 100644 --- a/doc/cmake.rst +++ b/doc/cmake.rst @@ -253,7 +253,7 @@ own toolchain file as listed in the cmake-toolchains_ documentation Or use the toolchain and scripts provided by the Android SDK and make changes using the ``ANDROID_*`` variables listed there. Where ```` is whatever -ndk version you have installed (tested with `23.2.8568313`) and ```` +ndk version you have installed (tested with `28.1.13356709`) and ```` is for android sdk platform, (tested with ``android-29``) .. warning:: diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index f95f1c7..342761e 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -95,7 +95,7 @@ class Wrapped { bool _property_can_revert(const StringName &p_name) const { return false; } bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return false; } void _validate_property(PropertyInfo &p_property) const {} - String _to_string() const { return "[" + String(get_class_static()) + ":" + itos(get_instance_id()) + "]"; } + String _to_string() const { return ""; } static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) {} static GDExtensionBool set_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value) { return false; } @@ -123,10 +123,6 @@ class Wrapped { return string_name; } - uint64_t get_instance_id() const { - return 0; - } - // Must be public but you should not touch this. GodotObject *_owner = nullptr; }; @@ -194,7 +190,9 @@ 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(); \ @@ -206,35 +204,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 \ diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index 65ab38a..b419c05 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -254,7 +254,7 @@ 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 - GDExtensionClassCreationInfo4 class_info = { + GDExtensionClassCreationInfo5 class_info = { p_virtual, // GDExtensionBool is_virtual; is_abstract, // GDExtensionBool is_abstract; p_exposed, // GDExtensionBool is_exposed; @@ -280,7 +280,7 @@ void ClassDB::_register_class(bool p_virtual, bool p_exposed, bool p_runtime) { (void *)&T::get_class_static(), // void *class_userdata; }; - internal::gdextension_interface_classdb_register_extension_class4(internal::library, cl.name._native_ptr(), cl.parent_name._native_ptr(), &class_info); + internal::gdextension_interface_classdb_register_extension_class5(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(); diff --git a/include/godot_cpp/core/defs.hpp b/include/godot_cpp/core/defs.hpp index 9d61c1c..08fe668 100644 --- a/include/godot_cpp/core/defs.hpp +++ b/include/godot_cpp/core/defs.hpp @@ -34,6 +34,7 @@ #include #include +#include #include namespace godot { diff --git a/include/godot_cpp/core/math_defs.hpp b/include/godot_cpp/core/math_defs.hpp index 8af85ee..a85cd94 100644 --- a/include/godot_cpp/core/math_defs.hpp +++ b/include/godot_cpp/core/math_defs.hpp @@ -46,6 +46,8 @@ namespace godot { #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 diff --git a/include/godot_cpp/core/method_bind.hpp b/include/godot_cpp/core/method_bind.hpp index e5291f4..8ddbf1d 100644 --- a/include/godot_cpp/core/method_bind.hpp +++ b/include/godot_cpp/core/method_bind.hpp @@ -49,14 +49,14 @@ namespace godot { class MethodBind { + uint32_t hint_flags = METHOD_FLAGS_DEFAULT; StringName name; StringName instance_class; int argument_count = 0; - uint32_t hint_flags = METHOD_FLAGS_DEFAULT; bool _static = false; - bool _is_const = false; - bool _has_return = false; + bool _const = false; + bool _returns = false; bool _vararg = false; std::vector argument_names; @@ -64,20 +64,20 @@ class MethodBind { std::vector default_arguments; protected: + void _set_const(bool p_const); + void _set_static(bool p_static); + void _set_returns(bool p_returns); + void _set_vararg(bool p_vararg); virtual GDExtensionVariantType gen_argument_type(int p_arg) const = 0; virtual PropertyInfo gen_argument_type_info(int p_arg) const = 0; - void generate_argument_types(int p_count); - void set_const(bool p_const); - void set_return(bool p_return); - void set_static(bool p_static); - void set_vararg(bool p_vararg); - void set_argument_count(int p_count); + void _generate_argument_types(int p_count); + + void set_argument_count(int p_count) { argument_count = p_count; } public: - StringName get_name() const; - void set_name(const StringName &p_name); - _FORCE_INLINE_ int get_default_argument_count() const { return (int)default_arguments.size(); } _FORCE_INLINE_ const std::vector &get_default_arguments() const { return default_arguments; } + _FORCE_INLINE_ int get_default_argument_count() const { return (int)default_arguments.size(); } + _FORCE_INLINE_ Variant has_default_argument(int p_arg) const { const int num_default_args = (int)(default_arguments.size()); const int idx = p_arg - (argument_count - num_default_args); @@ -98,19 +98,6 @@ class MethodBind { return default_arguments[idx]; } } - _FORCE_INLINE_ StringName get_instance_class() const { return instance_class; } - _FORCE_INLINE_ void set_instance_class(StringName p_class) { instance_class = p_class; } - - _FORCE_INLINE_ int get_argument_count() const { return argument_count; } - _FORCE_INLINE_ bool is_const() const { return _is_const; } - _FORCE_INLINE_ bool is_static() const { return _static; } - _FORCE_INLINE_ bool is_vararg() const { return _vararg; } - _FORCE_INLINE_ bool has_return() const { return _has_return; } - _FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags | (is_const() ? GDEXTENSION_METHOD_FLAG_CONST : 0) | (is_vararg() ? GDEXTENSION_METHOD_FLAG_VARARG : 0) | (is_static() ? GDEXTENSION_METHOD_FLAG_STATIC : 0); } - _FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; } - void set_argument_names(const std::vector &p_names); - std::vector get_argument_names() const; - void set_default_arguments(const std::vector &p_default_arguments) { default_arguments = p_default_arguments; } _FORCE_INLINE_ GDExtensionVariantType get_argument_type(int p_argument) const { ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, GDEXTENSION_VARIANT_TYPE_NIL); @@ -118,7 +105,6 @@ class MethodBind { } PropertyInfo get_argument_info(int p_argument) const; - virtual GDExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const = 0; std::vector get_arguments_info_list() const { std::vector vec; @@ -129,6 +115,31 @@ class MethodBind { } return vec; } + + void set_argument_names(const std::vector &p_names); + std::vector get_argument_names() const; + + virtual GDExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const = 0; + + _FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; } + _FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags | (is_const() ? GDEXTENSION_METHOD_FLAG_CONST : 0) | (is_vararg() ? GDEXTENSION_METHOD_FLAG_VARARG : 0) | (is_static() ? GDEXTENSION_METHOD_FLAG_STATIC : 0); } + _FORCE_INLINE_ StringName get_instance_class() const { return instance_class; } + _FORCE_INLINE_ void set_instance_class(StringName p_class) { instance_class = p_class; } + + _FORCE_INLINE_ int get_argument_count() const { return argument_count; } + + virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionCallError &r_error) const = 0; + virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return) const = 0; + + StringName get_name() const; + void set_name(const StringName &p_name); + _FORCE_INLINE_ bool is_const() const { return _const; } + _FORCE_INLINE_ bool is_static() const { return _static; } + _FORCE_INLINE_ bool is_vararg() const { return _vararg; } + _FORCE_INLINE_ bool has_return() const { return _returns; } + + void set_default_arguments(const std::vector &p_default_arguments) { default_arguments = p_default_arguments; } + std::vector get_arguments_metadata_list() const { std::vector vec; // First element is return value @@ -139,9 +150,6 @@ class MethodBind { return vec; } - virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionCallError &r_error) const = 0; - virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return) const = 0; - static void bind_call(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error); static void bind_ptrcall(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return); @@ -151,8 +159,7 @@ class MethodBind { template class MethodBindVarArgBase : public MethodBind { protected: - R(T::*method) - (const Variant **, GDExtensionInt, GDExtensionCallError &); + R (T::*method)(const Variant **, GDExtensionInt, GDExtensionCallError &); std::vector arguments; public: @@ -183,8 +190,8 @@ class MethodBindVarArgBase : public MethodBind { const MethodInfo &p_method_info, bool p_return_nil_is_variant) : method(p_method) { - set_vararg(true); - set_const(true); + _set_vararg(true); + _set_const(true); set_argument_count(p_method_info.arguments.size()); if (p_method_info.arguments.size()) { arguments = p_method_info.arguments; @@ -197,8 +204,8 @@ class MethodBindVarArgBase : public MethodBind { set_argument_names(names); } - generate_argument_types((int)p_method_info.arguments.size()); - set_return(should_returns); + _generate_argument_types((int)p_method_info.arguments.size()); + _set_returns(should_returns); } ~MethodBindVarArgBase() {} @@ -335,7 +342,7 @@ class MethodBindT : public MethodBind { MethodBindT(void (MB_T::*p_method)(P...)) { method = p_method; - generate_argument_types(sizeof...(P)); + _generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); } }; @@ -411,9 +418,9 @@ class MethodBindTC : public MethodBind { MethodBindTC(void (MB_T::*p_method)(P...) const) { method = p_method; - generate_argument_types(sizeof...(P)); + _generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); - set_const(true); + _set_const(true); } }; @@ -436,8 +443,7 @@ template template #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... @@ -494,9 +500,9 @@ class MethodBindTR : public MethodBind { MethodBindTR(R (MB_T::*p_method)(P...)) { method = p_method; - generate_argument_types(sizeof...(P)); + _generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); - set_return(true); + _set_returns(true); } }; @@ -519,8 +525,7 @@ template template #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... @@ -577,10 +582,10 @@ class MethodBindTRC : public MethodBind { MethodBindTRC(R (MB_T::*p_method)(P...) const) { method = p_method; - generate_argument_types(sizeof...(P)); + _generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); - set_return(true); - set_const(true); + _set_returns(true); + _set_const(true); } }; @@ -649,9 +654,9 @@ class MethodBindTS : public MethodBind { MethodBindTS(void (*p_function)(P...)) { function = p_function; - generate_argument_types(sizeof...(P)); + _generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); - set_static(true); + _set_static(true); } }; @@ -665,8 +670,7 @@ MethodBind *create_static_method_bind(void (*p_method)(P...)) { template class MethodBindTRS : public MethodBind { - R(*function) - (P...); + R (*function)(P...); protected: // GCC raises warnings in the case P = {} as the comparison is always false... @@ -718,10 +722,10 @@ class MethodBindTRS : public MethodBind { MethodBindTRS(R (*p_function)(P...)) { function = p_function; - generate_argument_types(sizeof...(P)); + _generate_argument_types(sizeof...(P)); set_argument_count(sizeof...(P)); - set_static(true); - set_return(true); + _set_static(true); + _set_returns(true); } }; diff --git a/include/godot_cpp/godot.hpp b/include/godot_cpp/godot.hpp index 8b200a7..253c8de 100644 --- a/include/godot_cpp/godot.hpp +++ b/include/godot_cpp/godot.hpp @@ -42,11 +42,11 @@ extern "C" GDExtensionInterfaceGetProcAddress gdextension_interface_get_proc_add extern "C" GDExtensionClassLibraryPtr library; extern "C" void *token; -extern "C" GDExtensionGodotVersion godot_version; +extern "C" GDExtensionGodotVersion2 godot_version; extern "C" GDExtensionRedotVersion redot_version; // All of the GDExtension interface functions. -extern "C" GDExtensionInterfaceGetGodotVersion gdextension_interface_get_godot_version; +extern "C" GDExtensionInterfaceGetGodotVersion2 gdextension_interface_get_godot_version2; extern "C" GDExtensionInterfaceGetRedotVersion gdextension_interface_get_redot_version; extern "C" GDExtensionInterfaceMemAlloc gdextension_interface_mem_alloc; extern "C" GDExtensionInterfaceMemRealloc gdextension_interface_mem_realloc; @@ -159,7 +159,6 @@ 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; @@ -185,10 +184,12 @@ 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" GDExtensionInterfaceClassdbGetMethodBind gdextension_interface_classdb_get_method_bind; extern "C" GDExtensionInterfaceClassdbGetClassTag gdextension_interface_classdb_get_class_tag; -extern "C" GDExtensionInterfaceClassdbRegisterExtensionClass4 gdextension_interface_classdb_register_extension_class4; +extern "C" GDExtensionInterfaceClassdbRegisterExtensionClass5 gdextension_interface_classdb_register_extension_class5; 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; @@ -206,6 +207,7 @@ extern "C" GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars gdextension_inter 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: @@ -230,6 +232,11 @@ class GDExtensionBinding { 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 { @@ -264,6 +271,13 @@ class GDExtensionBinding { 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; }; }; diff --git a/include/godot_cpp/variant/callable_method_pointer.hpp b/include/godot_cpp/variant/callable_method_pointer.hpp index 4cf75ee..910854b 100644 --- a/include/godot_cpp/variant/callable_method_pointer.hpp +++ b/include/godot_cpp/variant/callable_method_pointer.hpp @@ -106,8 +106,7 @@ template class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase { struct Data { T *instance; - R(T::*method) - (P...); + R (T::*method)(P...); } data; static_assert(sizeof(Data) % 4 == 0); @@ -148,8 +147,7 @@ template 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); @@ -229,8 +227,7 @@ Callable create_custom_callable_static_function_pointer(void (*p_method)(P...)) template class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase { struct Data { - R(*method) - (P...); + R (*method)(P...); } data; static_assert(sizeof(Data) % 4 == 0); diff --git a/include/godot_cpp/variant/char_string.hpp b/include/godot_cpp/variant/char_string.hpp index 445964a..e4916e4 100644 --- a/include/godot_cpp/variant/char_string.hpp +++ b/include/godot_cpp/variant/char_string.hpp @@ -115,7 +115,7 @@ class CharStringT { CharStringT &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); diff --git a/include/godot_cpp/variant/typed_array.hpp b/include/godot_cpp/variant/typed_array.hpp index 685cae6..192a55b 100644 --- a/include/godot_cpp/variant/typed_array.hpp +++ b/include/godot_cpp/variant/typed_array.hpp @@ -42,7 +42,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."); - _ref(p_array); + Array::operator=(p_array); } _FORCE_INLINE_ TypedArray(const Variant &p_variant) : TypedArray(Array(p_variant)) { @@ -50,7 +50,7 @@ class TypedArray : public Array { _FORCE_INLINE_ TypedArray(const Array &p_array) { set_typed(Variant::OBJECT, T::get_class_static(), Variant()); if (is_same_typed(p_array)) { - _ref(p_array); + Array::operator=(p_array); } else { assign(p_array); } @@ -70,7 +70,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."); \ - _ref(p_array); \ + Array::operator=(p_array); \ } \ _FORCE_INLINE_ TypedArray(std::initializer_list p_init) : \ Array(Array(p_init), m_variant_type, StringName(), Variant()) { \ @@ -81,7 +81,7 @@ class TypedArray : public Array { _FORCE_INLINE_ TypedArray(const Array &p_array) { \ set_typed(m_variant_type, StringName(), Variant()); \ if (is_same_typed(p_array)) { \ - _ref(p_array); \ + Array::operator=(p_array); \ } else { \ assign(p_array); \ } \ diff --git a/include/godot_cpp/variant/variant.hpp b/include/godot_cpp/variant/variant.hpp index 04b7067..88f5b1f 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -147,7 +147,7 @@ class Variant { static GDExtensionTypeFromVariantConstructorFunc to_type_constructor[VARIANT_MAX]; public: - _FORCE_INLINE_ GDExtensionVariantPtr _native_ptr() const { return const_cast(&opaque); } + _FORCE_INLINE_ GDExtensionVariantPtr _native_ptr() const { return const_cast(&opaque); } Variant(); Variant(std::nullptr_t n) : Variant() {} @@ -410,7 +410,8 @@ Array::ConstIterator Array::end() const { return Array::ConstIterator(ptr() + size()); } -Array::Array(std::initializer_list p_init) { +Array::Array(std::initializer_list p_init) : + Array() { ERR_FAIL_COND(resize(p_init.size()) != 0); size_t i = 0; diff --git a/pyproject.toml b/pyproject.toml index 0e9c4b4..0a51b3b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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 = "py37" +target-version = "py38" [tool.ruff.lint] extend-select = [ @@ -27,32 +27,32 @@ extend-select = [ ] [tool.codespell] -enable-colors = "" -write-changes = "" -check-hidden = "" +enable-colors = true +write-changes = true +check-hidden = true 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", +] diff --git a/src/core/class_db.cpp b/src/core/class_db.cpp index bec51f4..2b66367 100644 --- a/src/core/class_db.cpp +++ b/src/core/class_db.cpp @@ -394,7 +394,7 @@ void ClassDB::_editor_get_classes_used_callback(GDExtensionTypePtr p_packed_stri PackedStringArray *arr = reinterpret_cast(p_packed_string_array); arr->resize(instance_binding_callbacks.size()); int index = 0; - for (const std::pair &pair : instance_binding_callbacks) { + for (const std::pair &pair : instance_binding_callbacks) { (*arr)[index++] = pair.first; } } @@ -403,7 +403,7 @@ void ClassDB::initialize_class(const ClassInfo &p_cl) { } void ClassDB::initialize(GDExtensionInitializationLevel p_level) { - for (const std::pair pair : classes) { + for (const std::pair &pair : classes) { const ClassInfo &cl = pair.second; if (cl.level != p_level) { continue; diff --git a/src/core/method_bind.cpp b/src/core/method_bind.cpp index 7506273..1c6e9bc 100644 --- a/src/core/method_bind.cpp +++ b/src/core/method_bind.cpp @@ -34,32 +34,28 @@ namespace godot { -StringName MethodBind::get_name() const { - return name; +void MethodBind::_set_const(bool p_const) { + _const = p_const; } -void MethodBind::set_name(const StringName &p_name) { - name = p_name; -} - -void MethodBind::set_argument_count(int p_count) { - argument_count = p_count; +void MethodBind::_set_static(bool p_static) { + _static = p_static; } -void MethodBind::set_const(bool p_const) { - _is_const = p_const; +void MethodBind::_set_returns(bool p_returns) { + _returns = p_returns; } -void MethodBind::set_return(bool p_return) { - _has_return = p_return; +void MethodBind::_set_vararg(bool p_vararg) { + _vararg = p_vararg; } -void MethodBind::set_static(bool p_static) { - _static = p_static; +StringName MethodBind::get_name() const { + return name; } -void MethodBind::set_vararg(bool p_vararg) { - _vararg = p_vararg; +void MethodBind::set_name(const StringName &p_name) { + name = p_name; } void MethodBind::set_argument_names(const std::vector &p_names) { @@ -70,7 +66,7 @@ std::vector MethodBind::get_argument_names() const { return argument_names; } -void MethodBind::generate_argument_types(int p_count) { +void MethodBind::_generate_argument_types(int p_count) { set_argument_count(p_count); if (argument_types != nullptr) { diff --git a/src/godot.cpp b/src/godot.cpp index 4ecfde9..54eab01 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -49,11 +49,11 @@ GDExtensionInterfaceGetProcAddress gdextension_interface_get_proc_address = null GDExtensionClassLibraryPtr library = nullptr; void *token = nullptr; -GDExtensionGodotVersion godot_version = { 0, 0, 0, nullptr }; +GDExtensionGodotVersion2 godot_version = {}; GDExtensionRedotVersion redot_version = { 0, 0, 0, 0, nullptr, 0, nullptr, nullptr, 0, nullptr }; // All of the GDExtension interface functions. -GDExtensionInterfaceGetGodotVersion gdextension_interface_get_godot_version = nullptr; +GDExtensionInterfaceGetGodotVersion2 gdextension_interface_get_godot_version2 = nullptr; GDExtensionInterfaceGetRedotVersion gdextension_interface_get_redot_version = nullptr; GDExtensionInterfaceMemAlloc gdextension_interface_mem_alloc = nullptr; GDExtensionInterfaceMemRealloc gdextension_interface_mem_realloc = nullptr; @@ -166,7 +166,6 @@ GDExtensionInterfacePackedVector4ArrayOperatorIndex gdextension_interface_packed GDExtensionInterfacePackedVector4ArrayOperatorIndexConst gdextension_interface_packed_vector4_array_operator_index_const = nullptr; GDExtensionInterfaceArrayOperatorIndex gdextension_interface_array_operator_index = nullptr; GDExtensionInterfaceArrayOperatorIndexConst gdextension_interface_array_operator_index_const = nullptr; -GDExtensionInterfaceArrayRef gdextension_interface_array_ref = nullptr; GDExtensionInterfaceArraySetTyped gdextension_interface_array_set_typed = nullptr; GDExtensionInterfaceDictionaryOperatorIndex gdextension_interface_dictionary_operator_index = nullptr; GDExtensionInterfaceDictionaryOperatorIndexConst gdextension_interface_dictionary_operator_index_const = nullptr; @@ -192,10 +191,12 @@ GDExtensionInterfaceRefSetObject gdextension_interface_ref_set_object = nullptr; GDExtensionInterfaceScriptInstanceCreate3 gdextension_interface_script_instance_create3 = nullptr; GDExtensionInterfacePlaceHolderScriptInstanceCreate gdextension_interface_placeholder_script_instance_create = nullptr; GDExtensionInterfacePlaceHolderScriptInstanceUpdate gdextension_interface_placeholder_script_instance_update = nullptr; +GDExtensionInterfaceObjectGetScriptInstance gdextension_interface_object_get_script_instance = nullptr; +GDExtensionInterfaceObjectSetScriptInstance gdextension_interface_object_set_script_instance = nullptr; GDExtensionInterfaceClassdbConstructObject2 gdextension_interface_classdb_construct_object2 = nullptr; GDExtensionInterfaceClassdbGetMethodBind gdextension_interface_classdb_get_method_bind = nullptr; GDExtensionInterfaceClassdbGetClassTag gdextension_interface_classdb_get_class_tag = nullptr; -GDExtensionInterfaceClassdbRegisterExtensionClass4 gdextension_interface_classdb_register_extension_class4 = nullptr; +GDExtensionInterfaceClassdbRegisterExtensionClass5 gdextension_interface_classdb_register_extension_class5 = nullptr; GDExtensionInterfaceClassdbRegisterExtensionClassMethod gdextension_interface_classdb_register_extension_class_method = nullptr; GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod gdextension_interface_classdb_register_extension_class_virtual_method = nullptr; GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant gdextension_interface_classdb_register_extension_class_integer_constant = nullptr; @@ -213,6 +214,7 @@ GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8Chars gdextension_interface_editor GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen gdextension_interface_editor_help_load_xml_from_utf8_chars_and_len = nullptr; GDExtensionInterfaceImagePtrw gdextension_interface_image_ptrw = nullptr; GDExtensionInterfaceImagePtr gdextension_interface_image_ptr = nullptr; +GDExtensionInterfaceRegisterMainLoopCallbacks gdextension_interface_register_main_loop_callbacks = nullptr; struct DocData { const char *hash = nullptr; @@ -310,18 +312,14 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge internal::library = p_library; internal::token = p_library; - LOAD_PROC_ADDRESS(get_godot_version, GDExtensionInterfaceGetGodotVersion); - internal::gdextension_interface_get_godot_version(&internal::godot_version); + LOAD_PROC_ADDRESS(get_godot_version2, GDExtensionInterfaceGetGodotVersion2); + internal::gdextension_interface_get_godot_version2(&internal::godot_version); - internal::gdextension_interface_get_redot_version = (GDExtensionInterfaceGetRedotVersion)p_get_proc_address("get_redot_version"); - if (!internal::gdextension_interface_get_redot_version) { - ERR_PRINT_EARLY("Cannot load a GDExtension built for Redot using Godot or non-Redot derivative."); - return false; - } + LOAD_PROC_ADDRESS(get_redot_version, GDExtensionInterfaceGetRedotVersion); internal::gdextension_interface_get_redot_version(&internal::redot_version); - // Check that redot-cpp was compiled using an extension_api.json older or at the - // same version as the Redot that is loading it. + // Check that godot-cpp was compiled using an extension_api.json older or at the + // same version as the Godot that is loading it. bool compatible; if (internal::redot_version.major != REDOT_VERSION_MAJOR) { compatible = internal::redot_version.major > REDOT_VERSION_MAJOR; @@ -456,7 +454,6 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge LOAD_PROC_ADDRESS(packed_vector4_array_operator_index_const, GDExtensionInterfacePackedVector4ArrayOperatorIndexConst); LOAD_PROC_ADDRESS(array_operator_index, GDExtensionInterfaceArrayOperatorIndex); LOAD_PROC_ADDRESS(array_operator_index_const, GDExtensionInterfaceArrayOperatorIndexConst); - LOAD_PROC_ADDRESS(array_ref, GDExtensionInterfaceArrayRef); LOAD_PROC_ADDRESS(array_set_typed, GDExtensionInterfaceArraySetTyped); LOAD_PROC_ADDRESS(dictionary_operator_index, GDExtensionInterfaceDictionaryOperatorIndex); LOAD_PROC_ADDRESS(dictionary_operator_index_const, GDExtensionInterfaceDictionaryOperatorIndexConst); @@ -482,10 +479,12 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge LOAD_PROC_ADDRESS(script_instance_create3, GDExtensionInterfaceScriptInstanceCreate3); LOAD_PROC_ADDRESS(placeholder_script_instance_create, GDExtensionInterfacePlaceHolderScriptInstanceCreate); LOAD_PROC_ADDRESS(placeholder_script_instance_update, GDExtensionInterfacePlaceHolderScriptInstanceUpdate); + LOAD_PROC_ADDRESS(object_get_script_instance, GDExtensionInterfaceObjectGetScriptInstance); + LOAD_PROC_ADDRESS(object_set_script_instance, GDExtensionInterfaceObjectSetScriptInstance); LOAD_PROC_ADDRESS(classdb_construct_object2, GDExtensionInterfaceClassdbConstructObject2); LOAD_PROC_ADDRESS(classdb_get_method_bind, GDExtensionInterfaceClassdbGetMethodBind); LOAD_PROC_ADDRESS(classdb_get_class_tag, GDExtensionInterfaceClassdbGetClassTag); - LOAD_PROC_ADDRESS(classdb_register_extension_class4, GDExtensionInterfaceClassdbRegisterExtensionClass4); + LOAD_PROC_ADDRESS(classdb_register_extension_class5, GDExtensionInterfaceClassdbRegisterExtensionClass5); LOAD_PROC_ADDRESS(classdb_register_extension_class_method, GDExtensionInterfaceClassdbRegisterExtensionClassMethod); LOAD_PROC_ADDRESS(classdb_register_extension_class_virtual_method, GDExtensionInterfaceClassdbRegisterExtensionClassVirtualMethod); LOAD_PROC_ADDRESS(classdb_register_extension_class_integer_constant, GDExtensionInterfaceClassdbRegisterExtensionClassIntegerConstant); @@ -503,6 +502,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge LOAD_PROC_ADDRESS(editor_help_load_xml_from_utf8_chars_and_len, GDExtensionsInterfaceEditorHelpLoadXmlFromUtf8CharsAndLen); LOAD_PROC_ADDRESS(image_ptrw, GDExtensionInterfaceImagePtrw); LOAD_PROC_ADDRESS(image_ptr, GDExtensionInterfaceImagePtr); + LOAD_PROC_ADDRESS(register_main_loop_callbacks, GDExtensionInterfaceRegisterMainLoopCallbacks); r_initialization->initialize = initialize_level; r_initialization->deinitialize = deinitialize_level; @@ -533,6 +533,10 @@ void GDExtensionBinding::initialize_level(void *p_userdata, GDExtensionInitializ } level_initialized[p_level]++; + if ((ModuleInitializationLevel)p_level == MODULE_INITIALIZATION_LEVEL_CORE && init_data && init_data->has_main_loop_callbacks()) { + internal::gdextension_interface_register_main_loop_callbacks(internal::library, &init_data->main_loop_callbacks); + } + if ((ModuleInitializationLevel)p_level == MODULE_INITIALIZATION_LEVEL_EDITOR) { internal::gdextension_interface_editor_register_get_classes_used_callback(internal::library, &ClassDB::_editor_get_classes_used_callback); @@ -603,6 +607,18 @@ void GDExtensionBinding::InitObject::set_minimum_library_initialization_level(Mo init_data->minimum_initialization_level = static_cast(p_level); } +void GDExtensionBinding::InitObject::register_startup_callback(GDExtensionMainLoopStartupCallback p_callback) const { + init_data->main_loop_callbacks.startup_func = p_callback; +} + +void GDExtensionBinding::InitObject::register_frame_callback(GDExtensionMainLoopFrameCallback p_callback) const { + init_data->main_loop_callbacks.frame_func = p_callback; +} + +void GDExtensionBinding::InitObject::register_shutdown_callback(GDExtensionMainLoopShutdownCallback p_callback) const { + init_data->main_loop_callbacks.shutdown_func = p_callback; +} + GDExtensionBool GDExtensionBinding::InitObject::init() const { return GDExtensionBinding::init(get_proc_address, library, init_data, initialization); } diff --git a/src/variant/packed_arrays.cpp b/src/variant/packed_arrays.cpp index ef5505e..eb8e3f4 100644 --- a/src/variant/packed_arrays.cpp +++ b/src/variant/packed_arrays.cpp @@ -234,10 +234,6 @@ void Array::set_typed(uint32_t p_type, const StringName &p_class_name, const Var internal::gdextension_interface_array_set_typed((GDExtensionTypePtr *)this, (GDExtensionVariantType)p_type, (GDExtensionConstStringNamePtr)&p_class_name, (GDExtensionConstVariantPtr)&p_script); } -void Array::_ref(const Array &p_from) const { - internal::gdextension_interface_array_ref((GDExtensionTypePtr *)this, (GDExtensionConstTypePtr *)&p_from); -} - const Variant *Array::ptr() const { return (const Variant *)internal::gdextension_interface_array_operator_index_const((GDExtensionTypePtr *)this, 0); } diff --git a/test/project/main.gd b/test/project/main.gd index b69ad75..3d9ca7f 100644 --- a/test/project/main.gd +++ b/test/project/main.gd @@ -18,8 +18,7 @@ func _ready(): # To string. assert_equal(example.to_string(),'[ GDExtension::Example <--> Instance ID:%s ]' % example.get_instance_id()) - # It appears there's a bug with instance ids :-( - #assert_equal($Example/ExampleMin.to_string(), 'ExampleMin:[Wrapped:%s]' % $Example/ExampleMin.get_instance_id()) + assert_equal($Example/ExampleMin.to_string(), 'ExampleMin:' % $Example/ExampleMin.get_instance_id()) # Call static methods. assert_equal(Example.test_static(9, 100), 109); @@ -288,6 +287,13 @@ func _ready(): assert_equal(library_path, ProjectSettings.globalize_path(library_path)) assert_equal(FileAccess.file_exists(library_path), true) + # Test that internal classes work as expected (at least for Godot 4.5+). + assert_equal(ClassDB.can_instantiate("ExampleInternal"), false) + assert_equal(ClassDB.instantiate("ExampleInternal"), null) + var internal_class = example.test_get_internal_class() + assert_equal(internal_class.get_the_answer(), 42) + assert_equal(internal_class.get_class(), "ExampleInternal") + # Test a class with a unicode name. var przykład = ExamplePrzykład.new() assert_equal(przykład.get_the_word(), "słowo to przykład") diff --git a/test/src/example.cpp b/test/src/example.cpp index f51c1c1..9d3e62b 100644 --- a/test/src/example.cpp +++ b/test/src/example.cpp @@ -161,7 +161,7 @@ bool Example::_property_can_revert(const StringName &p_name) const { } else { return false; } -}; +} bool Example::_property_get_revert(const StringName &p_name, Variant &r_property) const { if (p_name == StringName("property_from_list")) { @@ -170,7 +170,7 @@ bool Example::_property_get_revert(const StringName &p_name, Variant &r_property } else { return false; } -}; +} void Example::_validate_property(PropertyInfo &p_property) const { String name = p_property.name; @@ -252,6 +252,8 @@ void Example::_bind_methods() { ClassDB::bind_method(D_METHOD("test_use_engine_singleton"), &Example::test_use_engine_singleton); + ClassDB::bind_method(D_METHOD("test_get_internal_class"), &Example::test_get_internal_class); + ClassDB::bind_static_method("Example", D_METHOD("test_static", "a", "b"), &Example::test_static); ClassDB::bind_static_method("Example", D_METHOD("test_static2"), &Example::test_static2); @@ -744,6 +746,12 @@ String Example::test_library_path() { return library_path; } +Ref Example::test_get_internal_class() const { + Ref it; + it.instantiate(); + return it; +} + int64_t Example::test_get_internal(const Variant &p_input) const { if (p_input.get_type() != Variant::INT) { return -1; @@ -779,3 +787,11 @@ void ExamplePrzykład::_bind_methods() { String ExamplePrzykład::get_the_word() const { return U"słowo to przykład"; } + +void ExampleInternal::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_the_answer"), &ExampleInternal::get_the_answer); +} + +int ExampleInternal::get_the_answer() const { + return 42; +} diff --git a/test/src/example.h b/test/src/example.h index b40fcab..403d59f 100644 --- a/test/src/example.h +++ b/test/src/example.h @@ -29,6 +29,8 @@ using namespace godot; +class ExampleInternal; + class ExampleRef : public RefCounted { GDCLASS(ExampleRef, RefCounted); @@ -58,7 +60,7 @@ class ExampleMin : public Control { GDCLASS(ExampleMin, Control); protected: - static void _bind_methods(){}; + static void _bind_methods() {} }; class Example : public Control { @@ -203,6 +205,8 @@ class Example : public Control { String test_use_engine_singleton() const; static String test_library_path(); + + Ref test_get_internal_class() const; }; VARIANT_ENUM_CAST(Example::Constants); @@ -288,3 +292,13 @@ class ExamplePrzykład : public RefCounted { public: String get_the_word() const; }; + +class ExampleInternal : public RefCounted { + GDCLASS(ExampleInternal, RefCounted); + +protected: + static void _bind_methods(); + +public: + int get_the_answer() const; +}; diff --git a/test/src/register_types.cpp b/test/src/register_types.cpp index d9290c8..c68176d 100644 --- a/test/src/register_types.cpp +++ b/test/src/register_types.cpp @@ -31,6 +31,7 @@ void initialize_example_module(ModuleInitializationLevel p_level) { GDREGISTER_CLASS(ExampleChild); GDREGISTER_RUNTIME_CLASS(ExampleRuntime); GDREGISTER_CLASS(ExamplePrzykład); + GDREGISTER_INTERNAL_CLASS(ExampleInternal); } void uninitialize_example_module(ModuleInitializationLevel p_level) { diff --git a/tools/android.py b/tools/android.py index fee4ed2..e63c1fd 100644 --- a/tools/android.py +++ b/tools/android.py @@ -9,7 +9,12 @@ def options(opts): opts.Add( "android_api_level", "Target Android API level", - "21", + "24", + ) + opts.Add( + "ndk_version", + "Fully qualified version of ndk to use for compilation.", + "28.1.13356709", ) opts.Add( "ANDROID_HOME", @@ -22,14 +27,9 @@ def exists(env): return get_android_ndk_root(env) is not None -# This must be kept in sync with the value in https://github.com/godotengine/godot/blob/master/platform/android/detect.py#L58. -def get_ndk_version(): - return "23.2.8568313" - - def get_android_ndk_root(env): if env["ANDROID_HOME"]: - return env["ANDROID_HOME"] + "/ndk/" + get_ndk_version() + return env["ANDROID_HOME"] + "/ndk/" + env["ndk_version"] else: return os.environ.get("ANDROID_NDK_ROOT") @@ -48,9 +48,9 @@ def generate(env): my_spawn.configure(env) # Validate API level - if int(env["android_api_level"]) < 21: - print("WARNING: minimum supported Android target api is 21. Forcing target api 21.") - env["android_api_level"] = "21" + if int(env["android_api_level"]) < 24: + print("WARNING: minimum supported Android target api is 24. Forcing target api 24.") + env["android_api_level"] = "24" # Setup toolchain toolchain = get_android_ndk_root(env) + "/toolchains/llvm/prebuilt/" @@ -68,7 +68,7 @@ def generate(env): if not os.path.exists(toolchain): print("ERROR: Could not find NDK toolchain at " + toolchain + ".") - print("Make sure NDK version " + get_ndk_version() + " is installed.") + print("Make sure NDK version " + env["ndk_version"] + " is installed.") env.Exit(1) env.PrependENVPath("PATH", toolchain + "/bin") # This does nothing half of the time, but we'll put it here anyways diff --git a/tools/godotcpp.py b/tools/godotcpp.py index ca64977..b751c47 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -16,12 +16,6 @@ from doc_source_generator import scons_generate_doc_source -def add_sources(sources, dir, extension): - for f in os.listdir(dir): - if f.endswith("." + extension): - sources.append(dir + "/" + f) - - def get_cmdline_bool(option, default): """We use `ARGUMENTS.get()` to check if options were manually overridden on the command line, and SCons' _text2bool helper to convert them to booleans, otherwise they're handled as strings. @@ -34,7 +28,12 @@ def get_cmdline_bool(option, default): def normalize_path(val, env): - return val if os.path.isabs(val) else os.path.join(env.Dir("#").abspath, val) + """Normalize a path that was provided by the user on the command line + and is thus either an absolute path, or relative to the top level directory (#) + where the command was run. + """ + # If val is an absolute path, it will not be joined. + return os.path.join(env.Dir("#").abspath, val) def validate_file(key, val, env): @@ -54,9 +53,10 @@ def validate_parent_dir(key, val, env): def get_platform_tools_paths(env): path = env.get("custom_tools", None) + tools_path = env.Dir("tools").srcnode().abspath if path is None: - return ["tools"] - return [normalize_path(path, env), "tools"] + return [tools_path] + return [normalize_path(path, env), tools_path] def get_custom_platforms(env): @@ -141,7 +141,12 @@ def scons_emit_files(target, source, env): env.Clean(target, [env.File(f) for f in get_file_list(str(source[0]), target[0].abspath, True, True)]) api = generate_trimmed_api(str(source[0]), profile_filepath) - files = [env.File(f) for f in _get_file_list(api, target[0].abspath, True, True)] + files = [] + for f in _get_file_list(api, target[0].abspath, True, True): + file = env.File(f) + if profile_filepath: + env.Depends(file, profile_filepath) + files.append(file) env["godot_cpp_gen_dir"] = target[0].abspath return files, source @@ -530,8 +535,11 @@ def generate(env): def _godot_cpp(env): - extension_dir = normalize_path(env.get("gdextension_dir", env.Dir("gdextension").abspath), env) - api_file = normalize_path(env.get("custom_api_file", env.File(extension_dir + "/extension_api.json").abspath), env) + extension_dir = normalize_path(env.get("gdextension_dir", default=env.Dir("gdextension").srcnode().abspath), env) + api_file = normalize_path( + env.get("custom_api_file", default=os.path.join(extension_dir, "extension_api.json")), env + ) + bindings = env.GodotCPPBindings( env.Dir("."), [ @@ -546,15 +554,22 @@ def _godot_cpp(env): env.NoCache(bindings) # Sources to compile - sources = [] - add_sources(sources, "src", "cpp") - add_sources(sources, "src/classes", "cpp") - add_sources(sources, "src/core", "cpp") - add_sources(sources, "src/variant", "cpp") - sources.extend([f for f in bindings if str(f).endswith(".cpp")]) + sources = [ + *env.Glob("src/*.cpp"), + *env.Glob("src/classes/*.cpp"), + *env.Glob("src/core/*.cpp"), + *env.Glob("src/variant/*.cpp"), + *tuple(f for f in bindings if str(f).endswith(".cpp")), + ] # Includes - env.AppendUnique(CPPPATH=[env.Dir(d) for d in [extension_dir, "include", "gen/include"]]) + env.AppendUnique( + CPPPATH=[ + env.Dir(extension_dir), + env.Dir("include").srcnode(), + env.Dir("gen/include"), + ] + ) library = None library_name = "libredot-cpp" + env["suffix"] + env["LIBSUFFIX"] diff --git a/tools/ios.py b/tools/ios.py index 25c17db..4e2a45c 100644 --- a/tools/ios.py +++ b/tools/ios.py @@ -36,9 +36,11 @@ def generate(env): if env["ios_simulator"]: sdk_name = "iphonesimulator" env.Append(CCFLAGS=["-mios-simulator-version-min=" + env["ios_min_version"]]) + env.Append(LINKFLAGS=["-mios-simulator-version-min=" + env["ios_min_version"]]) else: sdk_name = "iphoneos" env.Append(CCFLAGS=["-miphoneos-version-min=" + env["ios_min_version"]]) + env.Append(LINKFLAGS=["-miphoneos-version-min=" + env["ios_min_version"]]) if sys.platform == "darwin": if env["IOS_SDK_PATH"] == "":