Merge branch 'godotengine:master' into master
This commit is contained in:
commit
d4ca15c458
171
.clang-format
171
.clang-format
|
@ -1,29 +1,59 @@
|
|||
# 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 ###
|
||||
# chosen value in case the base style changes (last sync: Clang 18.1.8).
|
||||
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
|
||||
# AlignFunctionPointers: false
|
||||
# PadOperators: true
|
||||
# AlignConsecutiveBitFields:
|
||||
# Enabled: false
|
||||
# AcrossEmptyLines: false
|
||||
# AcrossComments: false
|
||||
# AlignCompound: false
|
||||
# AlignFunctionPointers: false
|
||||
# PadOperators: false
|
||||
# AlignConsecutiveDeclarations:
|
||||
# Enabled: false
|
||||
# AcrossEmptyLines: false
|
||||
# AcrossComments: false
|
||||
# AlignCompound: false
|
||||
# AlignFunctionPointers: false
|
||||
# PadOperators: false
|
||||
# AlignConsecutiveMacros:
|
||||
# Enabled: false
|
||||
# AcrossEmptyLines: false
|
||||
# AcrossComments: false
|
||||
# AlignCompound: false
|
||||
# AlignFunctionPointers: false
|
||||
# PadOperators: false
|
||||
# AlignConsecutiveShortCaseStatements:
|
||||
# Enabled: false
|
||||
# AcrossEmptyLines: false
|
||||
# AcrossComments: false
|
||||
# AlignCaseColons: false
|
||||
# AlignEscapedNewlines: Right
|
||||
AlignOperands: DontAlign
|
||||
AlignTrailingComments: false
|
||||
AlignTrailingComments:
|
||||
Kind: Never
|
||||
OverEmptyLines: 0
|
||||
# AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
# AllowShortEnumsOnASingleLine: true
|
||||
# AllowBreakBeforeNoexceptSpecifier: Never
|
||||
# AllowShortBlocksOnASingleLine: Never
|
||||
# AllowShortCaseLabelsOnASingleLine: false
|
||||
# AllowShortCompoundRequirementOnASingleLine: true
|
||||
# AllowShortEnumsOnASingleLine: true
|
||||
# AllowShortFunctionsOnASingleLine: All
|
||||
# AllowShortLambdasOnASingleLine: All
|
||||
# AllowShortIfStatementsOnASingleLine: Never
|
||||
# AllowShortLambdasOnASingleLine: All
|
||||
# AllowShortLoopsOnASingleLine: false
|
||||
# AlwaysBreakAfterDefinitionReturnType: None
|
||||
# AlwaysBreakAfterReturnType: None
|
||||
# AlwaysBreakBeforeMultilineStrings: false
|
||||
# AlwaysBreakTemplateDeclarations: MultiLine
|
||||
|
@ -31,6 +61,7 @@ AllowAllParametersOfDeclarationOnNextLine: false
|
|||
# - __capability
|
||||
# BinPackArguments: true
|
||||
# BinPackParameters: true
|
||||
# BitFieldColonSpacing: Both
|
||||
# BraceWrapping:
|
||||
# AfterCaseLabel: false
|
||||
# AfterClass: false
|
||||
|
@ -50,31 +81,29 @@ AllowAllParametersOfDeclarationOnNextLine: false
|
|||
# SplitEmptyFunction: true
|
||||
# SplitEmptyRecord: true
|
||||
# SplitEmptyNamespace: true
|
||||
# BreakAdjacentStringLiterals: true
|
||||
# BreakAfterAttributes: Leave
|
||||
# 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
|
||||
# CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
# DeriveLineEnding: true
|
||||
# DerivePointerAlignment: false
|
||||
# DisableFormat: false
|
||||
# EmptyLineAfterAccessModifier: Never
|
||||
# EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
# ExperimentalAutoDetectBinPacking: false
|
||||
# PackConstructorInitializers: BinPack
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
# AllowAllConstructorInitializersOnNextLine: true
|
||||
# FixNamespaceComments: true
|
||||
# ForEachMacros:
|
||||
# - foreach
|
||||
|
@ -84,116 +113,136 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
|||
# - KJ_IF_MAYBE
|
||||
# IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '".*"'
|
||||
- Regex: ^".*"$
|
||||
Priority: 1
|
||||
- Regex: '^<.*\.h>'
|
||||
- Regex: ^<.*\.h>$
|
||||
Priority: 2
|
||||
- Regex: '^<.*'
|
||||
- Regex: ^<.*>$
|
||||
Priority: 3
|
||||
# IncludeIsMainRegex: '(Test)?$'
|
||||
# IncludeIsMainRegex: (Test)?$
|
||||
# IncludeIsMainSourceRegex: ''
|
||||
# IndentAccessModifiers: false
|
||||
IndentCaseLabels: true
|
||||
# IndentCaseBlocks: false
|
||||
IndentCaseLabels: true
|
||||
# IndentExternBlock: AfterExternBlock
|
||||
# IndentGotoLabels: true
|
||||
# IndentPPDirectives: None
|
||||
# IndentExternBlock: AfterExternBlock
|
||||
# IndentRequires: false
|
||||
# IndentRequiresClause: true
|
||||
IndentWidth: 4
|
||||
# IndentWrappedFunctionNames: false
|
||||
# InsertBraces: false
|
||||
# InsertNewlineAtEOF: false
|
||||
# InsertTrailingCommas: None
|
||||
# IntegerLiteralSeparator:
|
||||
# Binary: 0
|
||||
# BinaryMinDigits: 0
|
||||
# Decimal: 0
|
||||
# DecimalMinDigits: 0
|
||||
# Hex: 0
|
||||
# HexMinDigits: 0
|
||||
JavaImportGroups:
|
||||
- org.godotengine
|
||||
- android
|
||||
- androidx
|
||||
- com.android
|
||||
- com.google
|
||||
- java
|
||||
- javax
|
||||
# JavaScriptQuotes: Leave
|
||||
# JavaScriptWrapImports: true
|
||||
# KeepEmptyLinesAtEOF: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
# LambdaBodyIndentation: Signature
|
||||
# Language: Cpp
|
||||
# LineEnding: DeriveLF
|
||||
# MacroBlockBegin: ''
|
||||
# MacroBlockEnd: ''
|
||||
# MaxEmptyLinesToKeep: 1
|
||||
# NamespaceIndentation: None
|
||||
# ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 4
|
||||
# ObjCBreakBeforeNestedBlockParam: true
|
||||
# ObjCSpaceAfterProperty: false
|
||||
# ObjCSpaceBeforeProtocolList: true
|
||||
# PPIndentWidth: -1
|
||||
PackConstructorInitializers: NextLine
|
||||
# PenaltyBreakAssignment: 2
|
||||
# PenaltyBreakBeforeFirstCallParameter: 19
|
||||
# PenaltyBreakComment: 300
|
||||
# PenaltyBreakFirstLessLess: 120
|
||||
# PenaltyBreakOpenParenthesis: 0
|
||||
# PenaltyBreakScopeResolution: 500
|
||||
# PenaltyBreakString: 1000
|
||||
# PenaltyBreakTemplateDeclaration: 10
|
||||
# PenaltyExcessCharacter: 1000000
|
||||
# PenaltyReturnTypeOnItsOwnLine: 60
|
||||
# PenaltyIndentedWhitespace: 0
|
||||
# PenaltyReturnTypeOnItsOwnLine: 60
|
||||
# PointerAlignment: Right
|
||||
# PPIndentWidth: -1
|
||||
# QualifierAlignment: Leave
|
||||
# ReferenceAlignment: Pointer
|
||||
# ReflowComments: true
|
||||
# RemoveBracesLLVM: false
|
||||
# RemoveParentheses: Leave
|
||||
# RemoveSemicolon: false
|
||||
# RequiresClausePosition: OwnLine
|
||||
# RequiresExpressionIndentation: OuterScope
|
||||
# SeparateDefinitionBlocks: Leave
|
||||
# ShortNamespaceLines: 1
|
||||
# SkipMacroDefinitionBody: false
|
||||
# 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
|
||||
# SpaceBeforeParens: ControlStatements
|
||||
# SpaceBeforeJsonColon: false
|
||||
# SpaceBeforeParensOptions:
|
||||
# AfterControlStatements: true
|
||||
# AfterForeachMacros: true
|
||||
# AfterFunctionDefinitionName: false
|
||||
# AfterFunctionDeclarationName: false
|
||||
# AfterFunctionDefinitionName: false
|
||||
# AfterIfMacros: true
|
||||
# AfterOverloadedOperator: false
|
||||
# AfterPlacementOperator: true
|
||||
# AfterRequiresInClause: false
|
||||
# AfterRequiresInExpression: false
|
||||
# BeforeNonEmptyParentheses: false
|
||||
# SpaceAroundPointerQualifiers: Default
|
||||
# SpaceBeforeRangeBasedForLoopColon: true
|
||||
# SpaceBeforeSquareBrackets: false
|
||||
# SpaceInEmptyBlock: false
|
||||
# SpaceInEmptyParentheses: false
|
||||
# SpacesBeforeTrailingComments: 1
|
||||
# SpacesInAngles: Never
|
||||
# SpacesInConditionalStatement: false
|
||||
# SpacesInContainerLiterals: true
|
||||
# SpacesInCStyleCastParentheses: false
|
||||
## Godot TODO: We'll want to use a min of 1, but we need to see how to fix
|
||||
## our comment capitalization at the same time.
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 0
|
||||
Maximum: -1
|
||||
# SpacesInParentheses: false
|
||||
# SpacesInParens: Never
|
||||
# SpacesInParensOptions:
|
||||
# InConditionalStatements: false
|
||||
# InCStyleCasts: false
|
||||
# InEmptyParentheses: false
|
||||
# Other: false
|
||||
# SpacesInSquareBrackets: false
|
||||
# SpaceBeforeSquareBrackets: false
|
||||
# BitFieldColonSpacing: Both
|
||||
Standard: c++17
|
||||
# StatementAttributeLikeMacros:
|
||||
# - Q_EMIT
|
||||
# StatementMacros:
|
||||
# - Q_UNUSED
|
||||
# - QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
# UseCRLF: false
|
||||
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
|
||||
|
|
|
@ -54,3 +54,6 @@ df61dc4b2bd54a5a40c515493c76f5a458e5b541
|
|||
|
||||
# Enforce template syntax `typename` over `class`
|
||||
9903e6779b70fc03aae70a37b9cf053f4f355b91
|
||||
|
||||
# Style: Apply new `clang-format` fixes
|
||||
b37fc1014abf7adda70dc30b0822d775b3a4433f
|
||||
|
|
|
@ -4,11 +4,7 @@
|
|||
|
||||
# Buildsystem
|
||||
|
||||
.* @godotengine/buildsystem
|
||||
.github/ @godotengine/buildsystem
|
||||
*.py @godotengine/buildsystem
|
||||
SConstruct @godotengine/buildsystem
|
||||
SCsub @godotengine/buildsystem
|
||||
* @godotengine/buildsystem
|
||||
|
||||
# Core
|
||||
|
||||
|
@ -21,7 +17,7 @@ SCsub @godotengine/buildsystem
|
|||
# Doc
|
||||
|
||||
/doc/ @godotengine/documentation
|
||||
doc_classes/* @godotengine/documentation
|
||||
**/doc_classes/ @godotengine/documentation
|
||||
|
||||
# Drivers
|
||||
|
||||
|
@ -76,24 +72,33 @@ doc_classes/* @godotengine/documentation
|
|||
# Modules
|
||||
|
||||
## Audio (+ video)
|
||||
/modules/interactive_music/ @godotengine/audio
|
||||
/modules/interactive_music/doc_classes/ @godotengine/audio @godotengine/documentation
|
||||
/modules/minimp3/ @godotengine/audio
|
||||
/modules/minimp3/doc_classes/ @godotengine/audio @godotengine/documentation
|
||||
/modules/ogg/ @godotengine/audio
|
||||
/modules/opus/ @godotengine/audio
|
||||
/modules/ogg/doc_classes/ @godotengine/audio @godotengine/documentation
|
||||
/modules/theora/ @godotengine/audio
|
||||
/modules/theora/doc_classes/ @godotengine/audio @godotengine/documentation
|
||||
/modules/vorbis/ @godotengine/audio
|
||||
/modules/webm/ @godotengine/audio
|
||||
/modules/vorbis/doc_classes/ @godotengine/audio @godotengine/documentation
|
||||
|
||||
## Import
|
||||
/modules/astcenc/ @godotengine/import
|
||||
/modules/basis_universal/ @godotengine/import
|
||||
/modules/betsy/ @godotengine/import
|
||||
/modules/bmp/ @godotengine/import
|
||||
/modules/cvtt/ @godotengine/import
|
||||
/modules/dds/ @godotengine/import
|
||||
/modules/etc/ @godotengine/import
|
||||
/modules/etcpak/ @godotengine/import
|
||||
/modules/fbx/ @godotengine/import
|
||||
/modules/fbx/doc_classes/ @godotengine/import @godotengine/documentation
|
||||
/modules/gltf/ @godotengine/import
|
||||
/modules/gltf/doc_classes/ @godotengine/import @godotengine/documentation
|
||||
/modules/gltf/tests/ @godotengine/import @godotengine/tests
|
||||
/modules/hdr/ @godotengine/import
|
||||
/modules/jpg/ @godotengine/import
|
||||
/modules/pvr/ @godotengine/import
|
||||
/modules/ktx/ @godotengine/import
|
||||
/modules/squish/ @godotengine/import
|
||||
/modules/svg/ @godotengine/import
|
||||
/modules/tga/ @godotengine/import
|
||||
|
@ -102,56 +107,98 @@ doc_classes/* @godotengine/documentation
|
|||
|
||||
## Network
|
||||
/modules/enet/ @godotengine/network
|
||||
/modules/enet/doc_classes/ @godotengine/network @godotengine/documentation
|
||||
/modules/mbedtls/ @godotengine/network
|
||||
/modules/mbedtls/tests/ @godotengine/network @godotengine/tests
|
||||
/modules/multiplayer/ @godotengine/network
|
||||
/modules/multiplayer/doc_classes/ @godotengine/network @godotengine/documentation
|
||||
/modules/upnp/ @godotengine/network
|
||||
/modules/upnp/doc_classes/ @godotengine/network @godotengine/documentation
|
||||
/modules/webrtc/ @godotengine/network
|
||||
/modules/webrtc/doc_classes/ @godotengine/network @godotengine/documentation
|
||||
/modules/websocket/ @godotengine/network
|
||||
/modules/websocket/doc_classes/ @godotengine/network @godotengine/documentation
|
||||
|
||||
## Physics
|
||||
/modules/godot_physics_2d/ @godotengine/physics
|
||||
/modules/godot_physics_3d/ @godotengine/physics
|
||||
|
||||
## Rendering
|
||||
/modules/denoise/ @godotengine/rendering
|
||||
/modules/glslang/ @godotengine/rendering
|
||||
/modules/lightmapper_rd/ @godotengine/rendering
|
||||
/modules/meshoptimizer/ @godotengine/rendering
|
||||
/modules/raycast/ @godotengine/rendering
|
||||
/modules/vhacd/ @godotengine/rendering
|
||||
/modules/xatlas_unwrap/ @godotengine/rendering
|
||||
|
||||
## Scripting
|
||||
/modules/gdscript/ @godotengine/gdscript
|
||||
/modules/jsonrpc/ @godotengine/gdscript
|
||||
/modules/gdscript/doc_classes/ @godotengine/gdscript @godotengine/documentation
|
||||
/modules/gdscript/icons/ @godotengine/gdscript @godotengine/usability
|
||||
/modules/gdscript/tests/ @godotengine/gdscript @godotengine/tests
|
||||
/modules/jsonrpc/ @godotengine/gdscript @godotengine/network
|
||||
/modules/jsonrpc/tests @godotengine/gdscript @godotengine/network @godotengine/tests
|
||||
/modules/mono/ @godotengine/dotnet
|
||||
/modules/mono/doc_classes/ @godotengine/dotnet @godotengine/documentation
|
||||
/modules/mono/icons/ @godotengine/dotnet @godotengine/usability
|
||||
|
||||
## Text
|
||||
/modules/freetype/ @godotengine/buildsystem
|
||||
/modules/msdfgen/ @godotengine/buildsystem
|
||||
/modules/text_server_adv/ @godotengine/gui-nodes
|
||||
/modules/text_server_adv/doc_classes/ @godotengine/gui-nodes @godotengine/documentation
|
||||
/modules/text_server_fb/ @godotengine/gui-nodes
|
||||
/modules/text_server_fb/doc_classes/ @godotengine/gui-nodes @godotengine/documentation
|
||||
|
||||
## XR
|
||||
/modules/camera/ @godotengine/xr
|
||||
/modules/gdextension/xr/ @godotengine/xr
|
||||
/modules/mobile_vr/ @godotengine/xr
|
||||
/modules/mobile_vr/doc_classes/ @godotengine/xr @godotengine/documentation
|
||||
/modules/openxr/ @godotengine/xr
|
||||
/modules/openxr/doc_classes/ @godotengine/xr @godotengine/documentation
|
||||
/modules/webxr/ @godotengine/xr
|
||||
/modules/webxr/doc_classes/ @godotengine/xr @godotengine/documentation
|
||||
|
||||
## Misc
|
||||
/modules/bullet/ @godotengine/physics
|
||||
/modules/csg/ @godotengine/3d-nodes
|
||||
/modules/gdnavigation/ @godotengine/navigation
|
||||
/modules/csg/doc_classes/ @godotengine/3d-nodes @godotengine/documentation
|
||||
/modules/csg/icons/ @godotengine/3d-nodes @godotengine/usability
|
||||
/modules/navigation/ @godotengine/navigation
|
||||
/modules/gridmap/ @godotengine/3d-nodes
|
||||
/modules/opensimplex/ @godotengine/3d-nodes
|
||||
/modules/gridmap/doc_classes/ @godotengine/3d-nodes @godotengine/documentation
|
||||
/modules/gridmap/icons/ @godotengine/3d-nodes @godotengine/usability
|
||||
/modules/noise/ @godotengine/core
|
||||
/modules/noise/doc_classes/ @godotengine/core @godotengine/documentation
|
||||
/modules/noise/icons/ @godotengine/core @godotengine/usability
|
||||
/modules/noise/tests/ @godotengine/core @godotengine/tests
|
||||
/modules/regex/ @godotengine/core
|
||||
/modules/regex/doc_classes/ @godotengine/core @godotengine/documentation
|
||||
/modules/regex/icons/ @godotengine/core @godotengine/usability
|
||||
/modules/regex/tests/ @godotengine/core @godotengine/tests
|
||||
/modules/zip/ @godotengine/core
|
||||
/modules/zip/doc_classes/ @godotengine/core @godotengine/documentation
|
||||
|
||||
# Platform
|
||||
|
||||
/platform/android/ @godotengine/android
|
||||
/platform/android/doc_classes/ @godotengine/android @godotengine/documentation
|
||||
/platform/ios/ @godotengine/ios
|
||||
/platform/ios/doc_classes/ @godotengine/ios @godotengine/documentation
|
||||
/platform/linuxbsd/ @godotengine/linux-bsd
|
||||
/platform/linuxbsd/doc_classes/ @godotengine/linux-bsd @godotengine/documentation
|
||||
/platform/macos/ @godotengine/macos
|
||||
/platform/macos/doc_classes/ @godotengine/macos @godotengine/documentation
|
||||
/platform/web/ @godotengine/web
|
||||
/platform/web/doc_classes/ @godotengine/web @godotengine/documentation
|
||||
/platform/windows/ @godotengine/windows
|
||||
/platform/windows/doc_classes/ @godotengine/windows @godotengine/documentation
|
||||
|
||||
# Scene
|
||||
|
||||
/scene/2d/ @godotengine/2d-nodes
|
||||
/scene/2d/physics/ @godotengine/2d-nodes @godotengine/physics
|
||||
/scene/3d/ @godotengine/3d-nodes
|
||||
/scene/3d/physics/ @godotengine/3d-nodes @godotengine/physics
|
||||
/scene/animation/ @godotengine/animation
|
||||
/scene/audio/ @godotengine/audio
|
||||
/scene/debugger/ @godotengine/debugger
|
||||
|
@ -162,6 +209,7 @@ doc_classes/* @godotengine/documentation
|
|||
/scene/resources/text_paragraph.* @godotengine/gui-nodes
|
||||
/scene/resources/visual_shader*.* @godotengine/shaders
|
||||
/scene/theme/ @godotengine/gui-nodes
|
||||
/scene/theme/icons/ @godotengine/gui-nodes @godotengine/usability
|
||||
|
||||
# Servers
|
||||
|
||||
|
@ -181,3 +229,9 @@ doc_classes/* @godotengine/documentation
|
|||
# Thirdparty
|
||||
|
||||
/thirdparty/ @godotengine/buildsystem
|
||||
|
||||
# Buildsystem (After everything to catch all)
|
||||
|
||||
*.py @godotengine/buildsystem
|
||||
SConstruct @godotengine/buildsystem
|
||||
SCsub @godotengine/buildsystem
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: Bug report
|
||||
description: Report a bug in Godot
|
||||
body:
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
name: Download Godot artifact
|
||||
description: Download the Godot artifact.
|
||||
|
||||
inputs:
|
||||
name:
|
||||
description: The artifact name.
|
||||
default: "${{ github.job }}"
|
||||
default: ${{ github.job }}
|
||||
path:
|
||||
description: The path to download and extract to.
|
||||
required: true
|
||||
default: "./"
|
||||
default: ./
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
using: composite
|
||||
steps:
|
||||
- name: Download Godot Artifact
|
||||
uses: actions/download-artifact@v4
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
name: Dump Godot API
|
||||
description: Dump Godot API for GDExtension
|
||||
|
||||
inputs:
|
||||
bin:
|
||||
description: The path to the Godot executable
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
using: composite
|
||||
steps:
|
||||
# Dump GDExtension interface and API
|
||||
- name: Dump GDExtension interface and API for godot-cpp build
|
||||
|
@ -19,5 +21,5 @@ runs:
|
|||
- name: Upload API dump
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
name: 'godot-api-dump'
|
||||
path: './godot-api/*'
|
||||
name: godot-api-dump
|
||||
path: ./godot-api/*
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
name: Build Godot
|
||||
description: Build Godot with the provided options.
|
||||
|
||||
inputs:
|
||||
target:
|
||||
description: Build target (editor, template_release, template_debug).
|
||||
default: "editor"
|
||||
default: editor
|
||||
tests:
|
||||
description: Unit tests.
|
||||
default: false
|
||||
|
@ -13,20 +14,21 @@ inputs:
|
|||
required: false
|
||||
sconsflags:
|
||||
description: Additional SCons flags.
|
||||
default: ""
|
||||
default: ''
|
||||
required: false
|
||||
scons-cache:
|
||||
description: The SCons cache path.
|
||||
default: "${{ github.workspace }}/.scons-cache/"
|
||||
default: ${{ github.workspace }}/.scons-cache/
|
||||
scons-cache-limit:
|
||||
description: The SCons cache size limit.
|
||||
# actions/cache has 10 GiB limit, and GitHub runners have a 14 GiB disk.
|
||||
# Limit to 7 GiB to avoid having the extracted cache fill the disk.
|
||||
default: 7168
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
using: composite
|
||||
steps:
|
||||
- name: Scons Build
|
||||
- name: SCons Build
|
||||
shell: sh
|
||||
env:
|
||||
SCONSFLAGS: ${{ inputs.sconsflags }}
|
||||
|
|
|
@ -3,12 +3,13 @@ description: Restore Godot build cache.
|
|||
inputs:
|
||||
cache-name:
|
||||
description: The cache base name (job name by default).
|
||||
default: "${{github.job}}"
|
||||
default: ${{ github.job }}
|
||||
scons-cache:
|
||||
description: The SCons cache path.
|
||||
default: "${{github.workspace}}/.scons-cache/"
|
||||
default: ${{ github.workspace }}/.scons-cache/
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
using: composite
|
||||
steps:
|
||||
- name: Restore SCons cache directory
|
||||
uses: actions/cache/restore@v4
|
||||
|
|
|
@ -3,12 +3,13 @@ description: Save Godot build cache.
|
|||
inputs:
|
||||
cache-name:
|
||||
description: The cache base name (job name by default).
|
||||
default: "${{github.job}}"
|
||||
default: ${{ github.job }}
|
||||
scons-cache:
|
||||
description: The SCons cache path.
|
||||
default: "${{github.workspace}}/.scons-cache/"
|
||||
default: ${{ github.workspace }}/.scons-cache/
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
using: composite
|
||||
steps:
|
||||
- name: Save SCons cache directory
|
||||
uses: actions/cache/save@v4
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
name: Test Godot project converter
|
||||
description: Test the Godot project converter.
|
||||
|
||||
inputs:
|
||||
bin:
|
||||
description: The path to the Godot executable
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
using: composite
|
||||
steps:
|
||||
- name: Test 3-to-4 conversion
|
||||
shell: sh
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
name: Setup Python and SCons
|
||||
description: Setup Python, install the pip version of SCons.
|
||||
|
||||
inputs:
|
||||
python-version:
|
||||
description: The Python version to use.
|
||||
default: "3.x"
|
||||
default: 3.x
|
||||
python-arch:
|
||||
description: The Python architecture.
|
||||
default: "x64"
|
||||
default: x64
|
||||
scons-version:
|
||||
description: The SCons version to use.
|
||||
default: "4.8.0"
|
||||
default: 4.8.0
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
using: composite
|
||||
steps:
|
||||
- name: Set up Python 3.x
|
||||
uses: actions/setup-python@v5
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
name: Test Godot project
|
||||
description: Run the test Godot project.
|
||||
|
||||
inputs:
|
||||
bin:
|
||||
description: The path to the Godot executable
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
using: composite
|
||||
steps:
|
||||
# Download and extract zip archive with project, folder is renamed to be able to easy change used project
|
||||
- name: Download test project
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
name: Upload Godot artifact
|
||||
description: Upload the Godot artifact.
|
||||
|
||||
inputs:
|
||||
name:
|
||||
description: The artifact name.
|
||||
default: "${{ github.job }}"
|
||||
default: ${{ github.job }}
|
||||
path:
|
||||
description: The path to upload.
|
||||
required: true
|
||||
default: "bin/*"
|
||||
default: bin/*
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
using: composite
|
||||
steps:
|
||||
- name: Upload Godot Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
|
|
|
@ -14,7 +14,7 @@ concurrency:
|
|||
|
||||
jobs:
|
||||
build-android:
|
||||
runs-on: "ubuntu-20.04"
|
||||
runs-on: ubuntu-20.04
|
||||
name: ${{ matrix.name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -39,7 +39,8 @@ jobs:
|
|||
sconsflags: arch=arm64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
@ -85,7 +86,7 @@ jobs:
|
|||
run: |
|
||||
cd platform/android/java
|
||||
./gradlew generateGodotEditor
|
||||
./gradlew generateGodotMetaEditor
|
||||
./gradlew generateGodotHorizonOSEditor
|
||||
cd ../../..
|
||||
ls -l bin/android_editor_builds/
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ env:
|
|||
# Used for the cache key. Add version suffix to force clean build.
|
||||
GODOT_BASE_BRANCH: master
|
||||
# Used for the godot-cpp checkout.
|
||||
GODOT_CPP_BRANCH: '4.3'
|
||||
GODOT_CPP_BRANCH: 4.3
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-cpp-tests
|
||||
|
@ -15,54 +15,50 @@ concurrency:
|
|||
|
||||
jobs:
|
||||
godot-cpp-tests:
|
||||
runs-on: "ubuntu-20.04"
|
||||
name: "Build and test Godot CPP"
|
||||
runs-on: ubuntu-20.04
|
||||
name: Build and test Godot CPP
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: .github
|
||||
|
||||
- name: Checkout godot-cpp
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
repository: godotengine/godot-cpp
|
||||
ref: ${{ env.GODOT_CPP_BRANCH }}
|
||||
path: godot-cpp
|
||||
|
||||
- name: Setup Python and SCons
|
||||
uses: ./.github/actions/godot-deps
|
||||
|
||||
# Checkout godot-cpp
|
||||
- name: Checkout godot-cpp
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: godotengine/godot-cpp
|
||||
ref: ${{ env.GODOT_CPP_BRANCH }}
|
||||
submodules: 'recursive'
|
||||
path: 'godot-cpp'
|
||||
- name: Setup GCC problem matcher
|
||||
uses: ammaraskar/gcc-problem-matcher@master
|
||||
|
||||
# Download generated API dump
|
||||
- name: Download GDExtension interface and API dump
|
||||
uses: ./.github/actions/download-artifact
|
||||
with:
|
||||
name: 'godot-api-dump'
|
||||
path: './godot-api'
|
||||
name: godot-api-dump
|
||||
path: ./godot-cpp/gdextension
|
||||
|
||||
# Extract and override existing files with generated files
|
||||
- name: Extract GDExtension interface and API dump
|
||||
run: |
|
||||
cp -f godot-api/gdextension_interface.h godot-cpp/gdextension/
|
||||
cp -f godot-api/extension_api.json godot-cpp/gdextension/
|
||||
# TODO: Enable caching when godot-cpp has proper cache limiting.
|
||||
|
||||
# TODO: Add caching to the SCons build and store it for CI via the godot-cache
|
||||
# action.
|
||||
# - name: Restore Godot build cache
|
||||
# uses: ./.github/actions/godot-cache-restore
|
||||
# with:
|
||||
# cache-name: godot-cpp
|
||||
# continue-on-error: true
|
||||
|
||||
# Build godot-cpp test extension
|
||||
- name: Build godot-cpp test extension
|
||||
run: |
|
||||
cd godot-cpp/test
|
||||
scons target=template_debug dev_build=yes
|
||||
cd ../..
|
||||
env: # Keep synced with godot-build.
|
||||
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
|
||||
SCONS_CACHE_LIMIT: 7168
|
||||
run: scons --directory=./godot-cpp/test target=template_debug dev_build=yes verbose=yes
|
||||
|
||||
gdextension-c-compile:
|
||||
runs-on: "ubuntu-20.04"
|
||||
name: "Check GDExtension header with a C compiler"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: "Run C compiler on gdextension_interface.h"
|
||||
run: |
|
||||
gcc -c core/extension/gdextension_interface.h
|
||||
# - name: Save Godot build cache
|
||||
# uses: ./.github/actions/godot-cache-save
|
||||
# with:
|
||||
# cache-name: godot-cpp
|
||||
# continue-on-error: true
|
||||
|
|
|
@ -14,11 +14,12 @@ concurrency:
|
|||
|
||||
jobs:
|
||||
ios-template:
|
||||
runs-on: "macos-latest"
|
||||
runs-on: macos-latest
|
||||
name: Template (target=template_release)
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ concurrency:
|
|||
|
||||
jobs:
|
||||
build-linux:
|
||||
runs-on: "ubuntu-20.04"
|
||||
runs-on: ubuntu-20.04
|
||||
name: ${{ matrix.name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -27,7 +27,7 @@ jobs:
|
|||
cache-name: linux-editor-mono
|
||||
target: editor
|
||||
sconsflags: module_mono_enabled=yes
|
||||
bin: "./bin/godot.linuxbsd.editor.x86_64.mono"
|
||||
bin: ./bin/godot.linuxbsd.editor.x86_64.mono
|
||||
build-mono: true
|
||||
tests: false # Disabled due freeze caused by mix Mono build and CI
|
||||
doc-test: true
|
||||
|
@ -40,7 +40,7 @@ jobs:
|
|||
target: editor
|
||||
# Debug symbols disabled as they're huge on this build and we hit the 14 GB limit for runners.
|
||||
sconsflags: dev_build=yes scu_build=yes debug_symbols=no precision=double use_asan=yes use_ubsan=yes linker=gold
|
||||
bin: "./bin/godot.linuxbsd.editor.dev.double.x86_64.san"
|
||||
bin: ./bin/godot.linuxbsd.editor.dev.double.x86_64.san
|
||||
build-mono: false
|
||||
tests: true
|
||||
proj-test: true
|
||||
|
@ -53,7 +53,7 @@ jobs:
|
|||
cache-name: linux-editor-llvm-sanitizers
|
||||
target: editor
|
||||
sconsflags: dev_build=yes use_asan=yes use_ubsan=yes use_llvm=yes linker=lld
|
||||
bin: "./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san"
|
||||
bin: ./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san
|
||||
build-mono: false
|
||||
tests: true
|
||||
# Skip 2GiB artifact speeding up action.
|
||||
|
@ -66,36 +66,37 @@ jobs:
|
|||
target: editor
|
||||
tests: true
|
||||
sconsflags: dev_build=yes use_tsan=yes use_llvm=yes linker=lld
|
||||
bin: "./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san"
|
||||
bin: ./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san
|
||||
build-mono: false
|
||||
# Skip 2GiB artifact speeding up action.
|
||||
artifact: false
|
||||
|
||||
- name: Template w/ Mono (target=template_release)
|
||||
- name: Template w/ Mono (target=template_release, tests=yes)
|
||||
cache-name: linux-template-mono
|
||||
target: template_release
|
||||
sconsflags: module_mono_enabled=yes tests=yes
|
||||
bin: "./bin/godot.linuxbsd.template_release.x86_64.mono"
|
||||
sconsflags: module_mono_enabled=yes
|
||||
bin: ./bin/godot.linuxbsd.template_release.x86_64.mono
|
||||
build-mono: false
|
||||
tests: true
|
||||
artifact: true
|
||||
|
||||
- name: Minimal template (target=template_release, everything disabled)
|
||||
- name: Minimal template (target=template_release, tests=yes, everything disabled)
|
||||
cache-name: linux-template-minimal
|
||||
target: template_release
|
||||
sconsflags: modules_enabled_by_default=no disable_3d=yes disable_advanced_gui=yes deprecated=no minizip=no tests=yes
|
||||
bin: "./bin/godot.linuxbsd.template_release.x86_64"
|
||||
sconsflags: modules_enabled_by_default=no disable_3d=yes disable_advanced_gui=yes deprecated=no minizip=no
|
||||
bin: ./bin/godot.linuxbsd.template_release.x86_64
|
||||
tests: true
|
||||
artifact: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
# Need newer mesa for lavapipe to work properly.
|
||||
- name: Linux dependencies for tests
|
||||
if: ${{ matrix.proj-test }}
|
||||
if: matrix.proj-test
|
||||
run: |
|
||||
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EB8B81E14DA65431D7504EA8F63F0F2B90935439
|
||||
|
@ -120,11 +121,11 @@ jobs:
|
|||
continue-on-error: true
|
||||
|
||||
- name: Setup Python and SCons
|
||||
if: ${{ ! matrix.legacy-scons }}
|
||||
if: '!matrix.legacy-scons'
|
||||
uses: ./.github/actions/godot-deps
|
||||
|
||||
- name: Setup Python and SCons (legacy versions)
|
||||
if: ${{ matrix.legacy-scons }}
|
||||
if: matrix.legacy-scons
|
||||
uses: ./.github/actions/godot-deps
|
||||
with:
|
||||
# Sync with Ensure*Version in SConstruct.
|
||||
|
@ -149,48 +150,48 @@ jobs:
|
|||
continue-on-error: true
|
||||
|
||||
- name: Generate C# glue
|
||||
if: ${{ matrix.build-mono }}
|
||||
if: matrix.build-mono
|
||||
run: |
|
||||
${{ matrix.bin }} --headless --generate-mono-glue ./modules/mono/glue
|
||||
|
||||
- name: Build .NET solutions
|
||||
if: ${{ matrix.build-mono }}
|
||||
if: matrix.build-mono
|
||||
run: |
|
||||
./modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --godot-platform=linuxbsd
|
||||
|
||||
- name: Prepare artifact
|
||||
if: ${{ matrix.artifact }}
|
||||
if: matrix.artifact
|
||||
run: |
|
||||
strip bin/godot.*
|
||||
chmod +x bin/godot.*
|
||||
|
||||
- name: Upload artifact
|
||||
uses: ./.github/actions/upload-artifact
|
||||
if: ${{ matrix.artifact }}
|
||||
if: matrix.artifact
|
||||
with:
|
||||
name: ${{ matrix.cache-name }}
|
||||
|
||||
- name: Dump Godot API
|
||||
uses: ./.github/actions/godot-api-dump
|
||||
if: ${{ matrix.api-dump }}
|
||||
if: matrix.api-dump
|
||||
with:
|
||||
bin: ${{ matrix.bin }}
|
||||
|
||||
- name: Unit tests
|
||||
if: ${{ matrix.tests }}
|
||||
if: matrix.tests
|
||||
run: |
|
||||
${{ matrix.bin }} --version
|
||||
${{ matrix.bin }} --help
|
||||
${{ matrix.bin }} --headless --test --force-colors
|
||||
|
||||
- name: .NET source generators tests
|
||||
if: ${{ matrix.build-mono }}
|
||||
if: matrix.build-mono
|
||||
run: |
|
||||
dotnet test modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests
|
||||
|
||||
# Check class reference
|
||||
- name: Check for class reference updates
|
||||
if: ${{ matrix.doc-test }}
|
||||
if: matrix.doc-test
|
||||
run: |
|
||||
echo "Running --doctool to see if this changes the public API without updating the documentation."
|
||||
echo -e "If a diff is shown, it means that your code/doc changes are incomplete and you should update the class reference with --doctool.\n\n"
|
||||
|
@ -199,20 +200,20 @@ jobs:
|
|||
|
||||
# Check API backwards compatibility
|
||||
- name: Check for GDExtension compatibility
|
||||
if: ${{ matrix.api-compat }}
|
||||
if: matrix.api-compat
|
||||
run: |
|
||||
./misc/scripts/validate_extension_api.sh "${{ matrix.bin }}"
|
||||
|
||||
# Download and run the test project
|
||||
- name: Test Godot project
|
||||
uses: ./.github/actions/godot-project-test
|
||||
if: ${{ matrix.proj-test }}
|
||||
if: matrix.proj-test
|
||||
with:
|
||||
bin: ${{ matrix.bin }}
|
||||
|
||||
# Test the project converter
|
||||
- name: Test project converter
|
||||
uses: ./.github/actions/godot-converter-test
|
||||
if: ${{ matrix.proj-conv }}
|
||||
if: matrix.proj-conv
|
||||
with:
|
||||
bin: ${{ matrix.bin }}
|
||||
|
|
|
@ -14,7 +14,7 @@ concurrency:
|
|||
|
||||
jobs:
|
||||
build-macos:
|
||||
runs-on: "macos-latest"
|
||||
runs-on: macos-latest
|
||||
name: ${{ matrix.name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -24,17 +24,18 @@ jobs:
|
|||
cache-name: macos-editor
|
||||
target: editor
|
||||
tests: true
|
||||
bin: "./bin/godot.macos.editor.universal"
|
||||
bin: ./bin/godot.macos.editor.universal
|
||||
|
||||
- name: Template (target=template_release)
|
||||
- name: Template (target=template_release, tests=yes)
|
||||
cache-name: macos-template
|
||||
target: template_release
|
||||
tests: true
|
||||
sconsflags: debug_symbols=no tests=yes
|
||||
bin: "./bin/godot.macos.template_release.universal"
|
||||
sconsflags: debug_symbols=no
|
||||
bin: ./bin/godot.macos.template_release.universal
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
@ -86,7 +87,7 @@ jobs:
|
|||
name: ${{ matrix.cache-name }}
|
||||
|
||||
- name: Unit tests
|
||||
if: ${{ matrix.tests }}
|
||||
if: matrix.tests
|
||||
run: |
|
||||
${{ matrix.bin }} --version
|
||||
${{ matrix.bin }} --help
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: 🔗 GHA
|
||||
on: [push, pull_request]
|
||||
on: [push, pull_request, merge_group]
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-runner
|
||||
|
@ -9,44 +9,38 @@ jobs:
|
|||
# First stage: Only static checks, fast and prevent expensive builds from running.
|
||||
|
||||
static-checks:
|
||||
if: ${{ vars.DISABLE_GODOT_CI == '' }}
|
||||
if: '!vars.DISABLE_GODOT_CI'
|
||||
name: 📊 Static checks
|
||||
uses: ./.github/workflows/static_checks.yml
|
||||
|
||||
# Second stage: Run all the builds and some of the tests.
|
||||
|
||||
android-build:
|
||||
if: ${{ vars.DISABLE_GODOT_CI == '' }}
|
||||
name: 🤖 Android
|
||||
needs: static-checks
|
||||
uses: ./.github/workflows/android_builds.yml
|
||||
|
||||
ios-build:
|
||||
if: ${{ vars.DISABLE_GODOT_CI == '' }}
|
||||
name: 🍏 iOS
|
||||
needs: static-checks
|
||||
uses: ./.github/workflows/ios_builds.yml
|
||||
|
||||
linux-build:
|
||||
if: ${{ vars.DISABLE_GODOT_CI == '' }}
|
||||
name: 🐧 Linux
|
||||
needs: static-checks
|
||||
uses: ./.github/workflows/linux_builds.yml
|
||||
|
||||
macos-build:
|
||||
if: ${{ vars.DISABLE_GODOT_CI == '' }}
|
||||
name: 🍎 macOS
|
||||
needs: static-checks
|
||||
uses: ./.github/workflows/macos_builds.yml
|
||||
|
||||
windows-build:
|
||||
if: ${{ vars.DISABLE_GODOT_CI == '' }}
|
||||
name: 🏁 Windows
|
||||
needs: static-checks
|
||||
uses: ./.github/workflows/windows_builds.yml
|
||||
|
||||
web-build:
|
||||
if: ${{ vars.DISABLE_GODOT_CI == '' }}
|
||||
name: 🌐 Web
|
||||
needs: static-checks
|
||||
uses: ./.github/workflows/web_builds.yml
|
||||
|
@ -56,7 +50,6 @@ jobs:
|
|||
# Can be turned off for PRs that intentionally break compat with godot-cpp,
|
||||
# until both the upstream PR and the matching godot-cpp changes are merged.
|
||||
godot-cpp-test:
|
||||
if: ${{ vars.DISABLE_GODOT_CI == '' }}
|
||||
name: 🪲 Godot CPP
|
||||
# This can be changed to depend on another platform, if we decide to use it for
|
||||
# godot-cpp instead. Make sure to move the .github/actions/godot-api-dump step
|
||||
|
|
|
@ -48,7 +48,7 @@ jobs:
|
|||
- name: Style checks via pre-commit
|
||||
uses: pre-commit/action@v3.0.1
|
||||
with:
|
||||
extra_args: --verbose --files ${{ env.CHANGED_FILES }}
|
||||
extra_args: --files ${{ env.CHANGED_FILES }}
|
||||
|
||||
- name: Python builders checks via pytest
|
||||
run: |
|
||||
|
@ -57,3 +57,7 @@ jobs:
|
|||
- name: Class reference schema checks
|
||||
run: |
|
||||
xmllint --noout --schema doc/class.xsd doc/classes/*.xml modules/*/doc_classes/*.xml platform/*/doc_classes/*.xml
|
||||
|
||||
- name: Run C compiler on `gdextension_interface.h`
|
||||
run: |
|
||||
gcc -c core/extension/gdextension_interface.h
|
||||
|
|
|
@ -8,7 +8,7 @@ env:
|
|||
GODOT_BASE_BRANCH: master
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no use_closure_compiler=yes strict_checks=yes
|
||||
EM_VERSION: 3.1.64
|
||||
EM_CACHE_FOLDER: "emsdk-cache"
|
||||
EM_CACHE_FOLDER: emsdk-cache
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-web
|
||||
|
@ -16,7 +16,7 @@ concurrency:
|
|||
|
||||
jobs:
|
||||
web-template:
|
||||
runs-on: "ubuntu-22.04"
|
||||
runs-on: ubuntu-22.04
|
||||
name: ${{ matrix.name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -37,7 +37,8 @@ jobs:
|
|||
artifact: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
@ -77,6 +78,6 @@ jobs:
|
|||
|
||||
- name: Upload artifact
|
||||
uses: ./.github/actions/upload-artifact
|
||||
if: ${{ matrix.artifact }}
|
||||
if: matrix.artifact
|
||||
with:
|
||||
name: ${{ matrix.cache-name }}
|
||||
|
|
|
@ -17,7 +17,7 @@ concurrency:
|
|||
jobs:
|
||||
build-windows:
|
||||
# Windows 10 with latest image
|
||||
runs-on: "windows-latest"
|
||||
runs-on: windows-latest
|
||||
name: ${{ matrix.name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -29,7 +29,7 @@ jobs:
|
|||
tests: true
|
||||
# Skip debug symbols, they're way too big with MSVC.
|
||||
sconsflags: debug_symbols=no vsproj=yes vsproj_gen_only=no windows_subsystem=console
|
||||
bin: "./bin/godot.windows.editor.x86_64.exe"
|
||||
bin: ./bin/godot.windows.editor.x86_64.exe
|
||||
artifact: true
|
||||
|
||||
- name: Editor w/ clang-cl (target=editor, tests=yes, use_llvm=yes)
|
||||
|
@ -39,16 +39,17 @@ jobs:
|
|||
sconsflags: debug_symbols=no windows_subsystem=console use_llvm=yes
|
||||
bin: ./bin/godot.windows.editor.x86_64.llvm.exe
|
||||
|
||||
- name: Template (target=template_release)
|
||||
- name: Template (target=template_release, tests=yes)
|
||||
cache-name: windows-template
|
||||
target: template_release
|
||||
tests: true
|
||||
sconsflags: debug_symbols=no tests=yes
|
||||
bin: "./bin/godot.windows.template_release.x86_64.console.exe"
|
||||
sconsflags: debug_symbols=no
|
||||
bin: ./bin/godot.windows.template_release.x86_64.console.exe
|
||||
artifact: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
@ -104,7 +105,7 @@ jobs:
|
|||
name: ${{ matrix.cache-name }}
|
||||
|
||||
- name: Unit tests
|
||||
if: ${{ matrix.tests }}
|
||||
if: matrix.tests
|
||||
run: |
|
||||
${{ matrix.bin }} --version
|
||||
${{ matrix.bin }} --help
|
||||
|
|
3
.mailmap
3
.mailmap
|
@ -84,6 +84,7 @@ Jean-Michel Bernard <jmb462@gmail.com>
|
|||
Jérôme Gully <jerome.gully0@gmail.com>
|
||||
JFonS <joan.fonssanchez@gmail.com>
|
||||
jitspoe <jitspoe@yahoo.com> <jitspoeAyahoooDcom>
|
||||
Johan Aires Rastén <johan@oljud.se>
|
||||
Juan Linietsky <reduzio@gmail.com>
|
||||
Juan Linietsky <reduzio@gmail.com> <juan@godotengine.org>
|
||||
Juan Linietsky <reduzio@gmail.com> <juan@okamstudio.com>
|
||||
|
@ -97,6 +98,7 @@ karroffel <therzog@mail.de> <thomas.herzog@simedis.com>
|
|||
Kelly Thomas <kelly.thomas@hotmail.com.au>
|
||||
Kongfa Waroros <gongpha@hotmail.com>
|
||||
K. S. Ernest (iFire) Lee <ernest.lee@chibifire.com>
|
||||
K. S. Ernest (iFire) Lee <ernest.lee@chibifire.com> <fire@users.noreply.github.com>
|
||||
kleonc <9283098+kleonc@users.noreply.github.com> <kleonc@users.noreply.github.com>
|
||||
Leon Krause <lk@leonkrause.com> <eska@eska.me>
|
||||
Leon Krause <lk@leonkrause.com> <eska014@users.noreply.github.com>
|
||||
|
@ -142,6 +144,7 @@ Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
|
|||
Pieter-Jan Briers <pieterjan.briers+git@gmail.com> <pieterjan.briers@gmail.com>
|
||||
Poommetee Ketson <poommetee@protonmail.com>
|
||||
Przemysław Gołąb (n-pigeon) <golab.przemyslaw@gmail.com>
|
||||
Radiant <69520693+RadiantUwU@users.noreply.github.com> <i.like.using.discord@gmail.com>
|
||||
Rafał Mikrut <mikrutrafal@protonmail.com>
|
||||
Rafał Mikrut <mikrutrafal@protonmail.com> <mikrutrafal54@gmail.com>
|
||||
Ralf Hölzemer <r.hoelzemer@posteo.de> <rollenrolm@posteo.de>
|
||||
|
|
|
@ -9,7 +9,7 @@ exclude: |
|
|||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v17.0.6
|
||||
rev: v19.1.0
|
||||
hooks:
|
||||
- id: clang-format
|
||||
files: \.(c|h|cpp|hpp|cc|hh|cxx|hxx|m|mm|inc|java|glsl)$
|
||||
|
@ -39,14 +39,14 @@ repos:
|
|||
stages: [manual] # Not automatically triggered, invoked via `pre-commit run --hook-stage manual clang-tidy`
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.4.4
|
||||
rev: v0.6.6
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--fix]
|
||||
- id: ruff-format
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.971
|
||||
rev: v1.11.2
|
||||
hooks:
|
||||
- id: mypy
|
||||
files: \.py$
|
||||
|
@ -96,16 +96,21 @@ repos:
|
|||
language: node
|
||||
entry: eslint
|
||||
files: ^(platform/web/js/|modules/|misc/dist/html/).*\.(js|html)$
|
||||
args: [--fix, --no-warn-ignored, --no-config-lookup, --config, platform/web/eslint.config.cjs]
|
||||
args:
|
||||
- --fix
|
||||
- --no-warn-ignored
|
||||
- --no-config-lookup
|
||||
- --config
|
||||
- platform/web/eslint.config.cjs
|
||||
additional_dependencies:
|
||||
- '@eslint/js@^9.3.0'
|
||||
- '@html-eslint/eslint-plugin@^0.24.1'
|
||||
- '@html-eslint/parser@^0.24.1'
|
||||
- '@stylistic/eslint-plugin@^2.1.0'
|
||||
- 'eslint@^9.3.0'
|
||||
- 'eslint-plugin-html@^8.1.1'
|
||||
- 'globals@^15.3.0'
|
||||
- 'espree@^10.0.1'
|
||||
- eslint@^9.3.0
|
||||
- eslint-plugin-html@^8.1.1
|
||||
- globals@^15.3.0
|
||||
- espree@^10.0.1
|
||||
|
||||
- id: jsdoc
|
||||
name: jsdoc
|
||||
|
@ -123,7 +128,7 @@ repos:
|
|||
- -d
|
||||
- dry-run
|
||||
pass_filenames: false
|
||||
additional_dependencies: ['jsdoc@^4.0.3']
|
||||
additional_dependencies: [jsdoc@^4.0.3]
|
||||
|
||||
- id: svgo
|
||||
name: svgo
|
||||
|
@ -131,7 +136,7 @@ repos:
|
|||
entry: svgo
|
||||
files: \.svg$
|
||||
args: [--quiet, --config, misc/utility/svgo.config.mjs]
|
||||
additional_dependencies: ["svgo@3.3.2"]
|
||||
additional_dependencies: [svgo@3.3.2]
|
||||
|
||||
- id: copyright-headers
|
||||
name: copyright-headers
|
||||
|
@ -179,7 +184,7 @@ repos:
|
|||
language: python
|
||||
entry: python misc/scripts/dotnet_format.py
|
||||
types_or: [c#]
|
||||
|
||||
#
|
||||
# End of upstream Godot pre-commit hooks.
|
||||
#
|
||||
# Keep this separation to let downstream forks add their own hooks to this file,
|
||||
|
|
34
AUTHORS.md
34
AUTHORS.md
|
@ -1,11 +1,17 @@
|
|||
# Godot Engine authors
|
||||
|
||||
Godot Engine is developed by a community of voluntary contributors who
|
||||
contribute code, bug reports, documentation, artwork, support, etc.
|
||||
contribute code, bug reports, documentation, translations, support, etc.,
|
||||
across multiple repositories.
|
||||
|
||||
It is impossible to list them all; nevertheless, this file aims at listing
|
||||
the developers who contributed significant patches to this MIT licensed
|
||||
source code. "Significant" is arbitrarily decided, but should be fair :)
|
||||
the developers who contributed significant improvements to the engine code.
|
||||
|
||||
To keep the list curated, we use a threshold of a minimum of 11 commits.
|
||||
|
||||
This file does not strictly reflect copyright ownership for the engine
|
||||
source code. For this, refer to the Git history to know which contributor
|
||||
wrote which part of the codebase.
|
||||
|
||||
GitHub usernames are indicated in parentheses, or as sole entry when no other
|
||||
name is available.
|
||||
|
@ -25,8 +31,6 @@ name is available.
|
|||
|
||||
## Developers
|
||||
|
||||
(in alphabetical order, with over 10 commits excluding merges)
|
||||
|
||||
Aaron Franke (aaronfranke)
|
||||
Aaron Pagano (aaronp64)
|
||||
Aaron Record (LightningAA)
|
||||
|
@ -38,6 +42,7 @@ name is available.
|
|||
Alfred Reinold Baudisch (alfredbaudisch)
|
||||
Alistair Leslie-Hughes (alesliehughes)
|
||||
Alket Rexhepi (alketii)
|
||||
Alvin Wong (alvinhochun)
|
||||
Andrea Catania (AndreaCatania)
|
||||
Andreia Gaita (shana)
|
||||
Andrii Doroshenko (Xrayez)
|
||||
|
@ -46,11 +51,13 @@ name is available.
|
|||
Angad Kambli (angad-k)
|
||||
Anilforextra (AnilBK)
|
||||
Anish Bhobe (KidRigger)
|
||||
Anni Ryynänen (anniryynanen)
|
||||
Anton Yabchinskiy (a12n)
|
||||
Anutrix
|
||||
Aren Villanueva (kurikaesu)
|
||||
Ariel Manzur (punto-)
|
||||
Arman Elgudzhyan (puchik)
|
||||
Arseny Kapoulkine (zeux)
|
||||
AThousandShips
|
||||
aXu-AP
|
||||
Bartłomiej T. Listwon (Listwon)
|
||||
|
@ -72,6 +79,7 @@ name is available.
|
|||
Carter Anderson (cart)
|
||||
ChibiDenDen
|
||||
Chris Bradfield (cbscribe)
|
||||
Chris Cranford (Naros)
|
||||
Christian Kaiser (ckaiser)
|
||||
Clay John (clayjohn)
|
||||
ConteZero
|
||||
|
@ -86,7 +94,9 @@ name is available.
|
|||
David Cambré (Gallilus)
|
||||
David Sichma (DavidSichma)
|
||||
David Snopek (dsnopek)
|
||||
derammo
|
||||
Dharkael (lupoDharkael)
|
||||
Dirk Steinmetz (rsjtdrjgfuzkfg)
|
||||
Dmitry Koteroff (Krakean)
|
||||
Dmitry Maganov (vonagam)
|
||||
Dominik Jasiński (dreamsComeTrue)
|
||||
|
@ -117,6 +127,7 @@ name is available.
|
|||
Geequlim
|
||||
George Marques (vnen)
|
||||
Gerrit Großkopf (Grosskopf)
|
||||
Giganzo
|
||||
Gilles Roudiere (groud)
|
||||
Gordon MacPherson (RevoluPowered)
|
||||
Guilherme Felipe de C. G. da Silva (guilhermefelipecgs)
|
||||
|
@ -126,7 +137,6 @@ name is available.
|
|||
Hein-Pieter van Braam-Stewart (hpvb)
|
||||
Hendrik Brucker (Geometror)
|
||||
Hilderin
|
||||
hilfazer
|
||||
Hiroshi Ogawa (hi-ogawa)
|
||||
HolonProduction
|
||||
homer666
|
||||
|
@ -151,6 +161,7 @@ name is available.
|
|||
Jia Jun Chai (SkyLucilfer)
|
||||
jitspoe
|
||||
Joan Fons Sanchez (JFonS)
|
||||
Johan Aires Rastén (JohanAR)
|
||||
Johan Manuel (29jm)
|
||||
Johannes Witt (HaSa1002)
|
||||
Jonathan Nicholl (jtnicholl)
|
||||
|
@ -163,11 +174,13 @@ name is available.
|
|||
Jummit
|
||||
Justo Delgado (mrcdk)
|
||||
karroffel
|
||||
Kassandra Pucher (PucklaJ)
|
||||
Kelly Thomas (KellyThomas)
|
||||
kleonc
|
||||
Kongfa Waroros (gongpha)
|
||||
Kostadin Damyanov (Max-Might)
|
||||
K. S. Ernest (iFire) Lee (fire)
|
||||
Kyle Eichlin (likeich)
|
||||
lawnjelly
|
||||
Leon Krause (leonkrause)
|
||||
Liz Haas (27thLiz)
|
||||
|
@ -185,6 +198,7 @@ name is available.
|
|||
Marcus Brummer (mbrlabs)
|
||||
Marcus Elg (MCrafterzz)
|
||||
Mariano Javier Suligoy (MarianoGnu)
|
||||
Mario Liebisch (MarioLiebisch)
|
||||
Mario Schlack (hurikhan)
|
||||
Marios Staikopoulos (marstaik)
|
||||
Marius Hanl (Maran23)
|
||||
|
@ -198,6 +212,7 @@ name is available.
|
|||
Masoud BH (masoudbh3)
|
||||
Mateo Kuruk Miccino (kuruk-mm)
|
||||
Matias N. Goldberg (darksylinc)
|
||||
Matthew Murphy (mashumafi)
|
||||
Matthew (skyace65)
|
||||
Matthias Hölzl (hoelzl)
|
||||
Max Hilbrunner (mhilbrunner)
|
||||
|
@ -209,9 +224,10 @@ name is available.
|
|||
MichiRecRoom (LikeLakers2)
|
||||
Micky (Mickeon)
|
||||
Mikael Hermansson (mihe)
|
||||
Mika Viskari (miv391)
|
||||
MinusKube
|
||||
MJacred
|
||||
Morris "Tabor" Arroad (mortarroad)
|
||||
Mounir Tohami (WhalesState)
|
||||
mrezai
|
||||
Muhammad Huri (CakHuri)
|
||||
muiroc
|
||||
|
@ -234,6 +250,7 @@ name is available.
|
|||
Patrick Dawson (pkdawson)
|
||||
Patrick Exner (FlameLizard)
|
||||
Patrick (firefly2442)
|
||||
patwork
|
||||
Paul Batty (Paulb23)
|
||||
Paul Joannon (paulloz)
|
||||
Paul Trojahn (ptrojahn)
|
||||
|
@ -245,6 +262,7 @@ name is available.
|
|||
Pieter-Jan Briers (PJB3005)
|
||||
Poommetee Ketson (Noshyaar)
|
||||
Przemysław Gołąb (n-pigeon)
|
||||
Radiant (RadiantUwU)
|
||||
Rafael M. G. (rafallus)
|
||||
Rafał Mikrut (qarmin)
|
||||
Raffaele Picca (RPicster)
|
||||
|
@ -282,6 +300,7 @@ name is available.
|
|||
Stanislav Labzyuk (DarkMessiah)
|
||||
Stijn Hinlopen (hinlopen)
|
||||
stmSi
|
||||
Stuart Carnie (stuartcarnie)
|
||||
Swarnim Arun (minraws)
|
||||
TC (floppyhammer)
|
||||
TechnoPorg
|
||||
|
@ -289,6 +308,7 @@ name is available.
|
|||
Thakee Nathees (ThakeeNathees)
|
||||
thebestnom
|
||||
Theo Hallenius (TheoXD)
|
||||
Thomas ten Cate (ttencate)
|
||||
Timo Schwarzer (timoschwarzer)
|
||||
Timothé Bonhoure (ajreckof)
|
||||
Timo (toger5)
|
||||
|
|
|
@ -63,6 +63,44 @@ Copyright: 2011, Ole Kniemeyer, MAXON, www.maxon.net
|
|||
2007-2014, Juan Linietsky, Ariel Manzur
|
||||
License: Expat and Zlib
|
||||
|
||||
Files: ./modules/godot_physics_2d/godot_joints_2d.cpp
|
||||
Comment: Chipmunk2D Joint Constraints
|
||||
Copyright: 2007, Scott Lembcke
|
||||
License: Expat
|
||||
|
||||
Files: ./modules/godot_physics_3d/gjk_epa.cpp
|
||||
./modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.cpp
|
||||
./modules/godot_physics_3d/joints/godot_generic_6dof_joint_3d.h
|
||||
./modules/godot_physics_3d/joints/godot_hinge_joint_3d.cpp
|
||||
./modules/godot_physics_3d/joints/godot_hinge_joint_3d_sw.h
|
||||
./modules/godot_physics_3d/joints/godot_jacobian_entry_3d_sw.h
|
||||
./modules/godot_physics_3d/joints/godot_pin_joint_3d.cpp
|
||||
./modules/godot_physics_3d/joints/godot_pin_joint_3d.h
|
||||
./modules/godot_physics_3d/joints/godot_slider_joint_3d.cpp
|
||||
./modules/godot_physics_3d/joints/godot_slider_joint_3d.h
|
||||
./modules/godot_physics_3d/godot_soft_body_3d.cpp
|
||||
./modules/godot_physics_3d/godot_soft_body_3d.h
|
||||
./modules/godot_physics_3d/godot_shape_3d.cpp
|
||||
./modules/godot_physics_3d/godot_shape_3d.h
|
||||
Comment: Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright: 2003-2008, Erwin Coumans
|
||||
2014-present, Godot Engine contributors
|
||||
2007-2014, Juan Linietsky, Ariel Manzur
|
||||
License: Expat and Zlib
|
||||
|
||||
Files: ./modules/godot_physics_3d/godot_collision_solver_3d_sat.cpp
|
||||
Comment: Open Dynamics Engine
|
||||
Copyright: 2001-2003, Russell L. Smith, Alen Ladavac, Nguyen Binh
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: ./modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.cpp
|
||||
./modules/godot_physics_3d/joints/godot_cone_twist_joint_3d.h
|
||||
Comment: Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright: 2007, Starbreeze Studios
|
||||
2014-present, Godot Engine contributors
|
||||
2007-2014, Juan Linietsky, Ariel Manzur
|
||||
License: Expat and Zlib
|
||||
|
||||
Files: ./modules/lightmapper_rd/lm_compute.glsl
|
||||
Comment: Joint Non-Local Means (JNLM) denoiser
|
||||
Copyright: 2020, Manuel Prandini
|
||||
|
@ -93,44 +131,6 @@ Copyright: 2001, Robert Penner
|
|||
2007-2014, Juan Linietsky, Ariel Manzur
|
||||
License: Expat
|
||||
|
||||
Files: ./servers/physics_2d/godot_joints_2d.cpp
|
||||
Comment: Chipmunk2D Joint Constraints
|
||||
Copyright: 2007, Scott Lembcke
|
||||
License: Expat
|
||||
|
||||
Files: ./servers/physics_3d/collision_solver_3d_sat.cpp
|
||||
Comment: Open Dynamics Engine
|
||||
Copyright: 2001-2003, Russell L. Smith, Alen Ladavac, Nguyen Binh
|
||||
License: BSD-3-clause
|
||||
|
||||
Files: ./servers/physics_3d/gjk_epa.cpp
|
||||
./servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp
|
||||
./servers/physics_3d/joints/generic_6dof_joint_3d_sw.h
|
||||
./servers/physics_3d/joints/hinge_joint_3d_sw.cpp
|
||||
./servers/physics_3d/joints/hinge_joint_3d_sw.h
|
||||
./servers/physics_3d/joints/jacobian_entry_3d_sw.h
|
||||
./servers/physics_3d/joints/pin_joint_3d_sw.cpp
|
||||
./servers/physics_3d/joints/pin_joint_3d_sw.h
|
||||
./servers/physics_3d/joints/slider_joint_3d_sw.cpp
|
||||
./servers/physics_3d/joints/slider_joint_3d_sw.h
|
||||
./servers/physics_3d/soft_body_3d_sw.cpp
|
||||
./servers/physics_3d/soft_body_3d_sw.h
|
||||
./servers/physics_3d/shape_3d_sw.cpp
|
||||
./servers/physics_3d/shape_3d_sw.h
|
||||
Comment: Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright: 2003-2008, Erwin Coumans
|
||||
2014-present, Godot Engine contributors
|
||||
2007-2014, Juan Linietsky, Ariel Manzur
|
||||
License: Expat and Zlib
|
||||
|
||||
Files: ./servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp
|
||||
./servers/physics_3d/joints/cone_twist_joint_3d_sw.h
|
||||
Comment: Bullet Continuous Collision Detection and Physics Library
|
||||
Copyright: 2007, Starbreeze Studios
|
||||
2014-present, Godot Engine contributors
|
||||
2007-2014, Juan Linietsky, Ariel Manzur
|
||||
License: Expat and Zlib
|
||||
|
||||
Files: ./servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl
|
||||
./servers/rendering/renderer_rd/shaders/ssao_blur.glsl
|
||||
./servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl
|
||||
|
|
75
DONORS.md
75
DONORS.md
|
@ -12,12 +12,12 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
|
||||
## Patrons
|
||||
|
||||
Khronos® Group <https://www.khronos.org/>
|
||||
OSS Capital <https://oss.capital/>
|
||||
Re-Logic <https://re-logic.com/>
|
||||
|
||||
## Platinum sponsors
|
||||
|
||||
Google Play <https://play.google.com/>
|
||||
Google Play <https://play.google.com>
|
||||
Ramatak <https://ramatak.com/>
|
||||
V-Sekai <https://github.com/V-Sekai>
|
||||
W4 Games <https://w4games.com/>
|
||||
|
@ -25,53 +25,56 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
## Gold sponsors
|
||||
|
||||
Mega Crit <https://www.megacrit.com/>
|
||||
Pirate Software <https://gopiratesoftware.com/>
|
||||
Prehensile Tales <https://prehensile-tales.com/>
|
||||
Pirate Software <https://gopiratesoftware.com>
|
||||
Prehensile Tales <https://prehensile-tales.com>
|
||||
Robot Gentleman <http://robotgentleman.com/>
|
||||
|
||||
## Silver sponsors
|
||||
|
||||
Broken Rules <https://brokenrul.es/>
|
||||
Chasing Carrots <https://www.chasing-carrots.com/>
|
||||
Broken Rules <https://brokenrul.es>
|
||||
Chasing Carrots <https://www.chasing-carrots.com>
|
||||
Copia Wealth Studios <https://copiawealthstudios.com/>
|
||||
Indoor Astronaut <https://indoorastronaut.ch/>
|
||||
LoadComplete <https://loadcomplete.com/>
|
||||
Null <https://null.com/>
|
||||
Orbital Knight <https://www.orbitalknight.com/>
|
||||
Playful Studios <https://playfulstudios.com/>
|
||||
Re-Logic <https://re-logic.com/>
|
||||
|
||||
## Diamond members
|
||||
|
||||
Bippinbits <http://domekeepergame.com/>
|
||||
Sealow
|
||||
And 5 anonymous donors
|
||||
Sylv <https://rankith.itch.io/unnamed-space-idle-prototype>
|
||||
And 3 anonymous donors
|
||||
|
||||
## Titanium members
|
||||
|
||||
Adriaan de Jongh <https://adriaan.games/>
|
||||
Anitya Space <https://www.anitya.space/>
|
||||
Adriaan de Jongh <https://adriaan.games>
|
||||
Anitya Space <https://www.anitya.space>
|
||||
Basically Games
|
||||
FDG Entertainment <https://www.fdg-entertainment.com/>
|
||||
Game Dev Artisan <https://gamedevartisan.com/>
|
||||
FDG Entertainment <https://www.fdg-entertainment.com>
|
||||
Game Dev Artisan <https://gamedevartisan.com>
|
||||
Garry Newman
|
||||
Isaiah Smith <https://www.isaiahsmith.dev/>
|
||||
Libretrend <https://libretrend.com/>
|
||||
Kenney <https://kenney.nl/>
|
||||
Libretrend <https://libretrend.com>
|
||||
Life Art Studios <https://lifeartstudios.net/>
|
||||
Lucid Silence Games
|
||||
Matthew Campbell
|
||||
PolyMars <https://polymars.dev/>
|
||||
RPG in a Box <https://www.rpginabox.com/>
|
||||
Razenpok <https://www.youtube.com/watch?v=-QxI-RP6-HM>
|
||||
Smirk Software <https://smirk.gg/>
|
||||
RPG in a Box <https://www.rpginabox.com>
|
||||
Smirk Software <https://smirk.gg>
|
||||
Studio Sunshower <https://www.studiosunshower.com/>
|
||||
TrampolineTales <https://TrampolineTales.com/>
|
||||
粟二华 (Su Erhua)
|
||||
And 6 anonymous donors
|
||||
And 4 anonymous donors
|
||||
|
||||
## Platinum members
|
||||
|
||||
Andy Touch
|
||||
BlockImperiumGames (BIG)
|
||||
Christoph Woinke
|
||||
Christopher Shifflett
|
||||
Christoph Woinke
|
||||
Cody Bentley
|
||||
Darrin Massena
|
||||
Edward Flick
|
||||
|
@ -79,8 +82,8 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
HP van Braam
|
||||
iCommitGames
|
||||
Jonah Stich
|
||||
Justo Delgado Baudí
|
||||
katnamag
|
||||
Marek Belski
|
||||
Matthew Ekenstedt
|
||||
Memories in 8Bit
|
||||
Mike King
|
||||
|
@ -97,13 +100,14 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
TigerJ
|
||||
Violin Iliev
|
||||
Vladimír Chvátil
|
||||
And 16 anonymous donors
|
||||
And 13 anonymous donors
|
||||
|
||||
## Gold members
|
||||
|
||||
80px
|
||||
afreytes
|
||||
alMoo Games
|
||||
alMoo Games
|
||||
Alva Majo
|
||||
Antti Vesanen
|
||||
Asher Glick
|
||||
|
@ -119,6 +123,8 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Bryce Dixon
|
||||
c64cosmin
|
||||
Carlo del Mundo
|
||||
Carl van der Geest
|
||||
Chocolate Software
|
||||
Cindy Trieu
|
||||
ClarkThyLord
|
||||
Codex404
|
||||
|
@ -135,17 +141,21 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
dgehrig
|
||||
dhanielk
|
||||
Distorted Realities
|
||||
Donkung
|
||||
Dono
|
||||
Don't You Know Who I Am? Inc.
|
||||
Dustuu
|
||||
Dylan P.
|
||||
Edelweiss
|
||||
Ends
|
||||
Eren Ogrul
|
||||
Eric Brand
|
||||
Eric Phy
|
||||
Faisal Al-Kubaisi (QatariGameDev)
|
||||
Felix Adam
|
||||
FeralBytes
|
||||
Festzeltgaming.de
|
||||
Frozen Fractal
|
||||
Gaudipern
|
||||
GlassBrick
|
||||
Grau
|
||||
|
@ -153,6 +163,7 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Hayden Oliver
|
||||
hiulit
|
||||
Illyan
|
||||
Immaculate Lift Studio
|
||||
Ivan Tabashki
|
||||
Jacob (HACKhalo2 Studios)
|
||||
Jam
|
||||
|
@ -160,13 +171,12 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Javier Roman
|
||||
Jeff Hungerford
|
||||
Jeronimo Schreyer
|
||||
Joel Martinez
|
||||
Johannes Wuensch
|
||||
John Gabriel
|
||||
Jonas Yamazaki
|
||||
Jonathan
|
||||
José Canepa
|
||||
Joshua Stelly
|
||||
Justin Sasso
|
||||
Kalydi Balázs
|
||||
KAR Games
|
||||
Kiri "ExpiredPopsicle" Artemis
|
||||
|
@ -181,7 +191,9 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
m1n1ster
|
||||
Manuel Requena
|
||||
Mara Huldra
|
||||
Marek Belski
|
||||
Martin Šenkeřík
|
||||
MHDante
|
||||
Michael Gooch
|
||||
Modus Ponens
|
||||
Moshe Harris
|
||||
|
@ -190,6 +202,7 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Nassor Paulino da Silva
|
||||
nezticle
|
||||
Niklas Wahrman
|
||||
Nitzan Bueno
|
||||
Niwl Games
|
||||
NotNet
|
||||
Oathbringer
|
||||
|
@ -207,6 +220,7 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
re:thinc
|
||||
Richard Ivánek
|
||||
Rudi P
|
||||
Sam Leathers
|
||||
Samuel Judd
|
||||
ScoreSpace
|
||||
Shiny Shinken
|
||||
|
@ -238,12 +252,12 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Zhu Li
|
||||
zikes
|
||||
嗯大爷
|
||||
潘彦圣
|
||||
|
||||
Alex Khayrullin
|
||||
Algebrute
|
||||
Andriy
|
||||
Antanas Paskauskas
|
||||
anti666
|
||||
Ari
|
||||
Arisaka Mayuki
|
||||
Arthur S. Muszynski
|
||||
|
@ -269,13 +283,11 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Liam Smyth
|
||||
LoparPanda
|
||||
Martin Gulliksson
|
||||
Martin Soucek
|
||||
Michael Dürwald
|
||||
Michael Policastro
|
||||
n00sh
|
||||
Nicolás Monner Sans
|
||||
Nikita Rotskov
|
||||
Nikola Whallon
|
||||
Oliver Dick
|
||||
Patrick Wuttke
|
||||
Pete Goodwin
|
||||
|
@ -298,7 +310,6 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
VoidPointer
|
||||
Yifan Lai
|
||||
|
||||
Aaron Mayfield
|
||||
Adam Carr
|
||||
Adam Smeltzer
|
||||
Adisibio
|
||||
|
@ -315,7 +326,6 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Ano Nim
|
||||
Arch Toasty
|
||||
Arda Erol
|
||||
A Really Tall Horse
|
||||
Arturo Rosales
|
||||
Ash K
|
||||
Aubrey Falconer
|
||||
|
@ -343,6 +353,7 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Dakota Watkins
|
||||
Daniele Tolomelli
|
||||
Daniel Ramos
|
||||
Daren Scot Wilson
|
||||
Dave Jansen
|
||||
Davesnothere
|
||||
David Baker
|
||||
|
@ -361,12 +372,11 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Eric Stokes
|
||||
Eric Williams
|
||||
Erkki Seppälä
|
||||
Ewan Holmes
|
||||
Felix Adam
|
||||
Frank
|
||||
Frying☆Pan
|
||||
Game Endeavor
|
||||
gamerminstrel
|
||||
Garrett S
|
||||
Gary Thomas
|
||||
gebba
|
||||
Greyson Richey
|
||||
|
@ -385,7 +395,6 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Jamie Massey
|
||||
JARKKO PARVIAINEN
|
||||
Jason Evans
|
||||
Joakim Askenbäck
|
||||
Jonas
|
||||
Jonas Arndt
|
||||
Jonas Yamazaki
|
||||
|
@ -421,7 +430,6 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Martin Holas
|
||||
Martin Liška
|
||||
Martin Trbola
|
||||
Matěj Drábek
|
||||
Mathieu
|
||||
Matt Edwards
|
||||
Maverick
|
||||
|
@ -441,7 +449,6 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Neofytos Chimonas
|
||||
Nerdforge
|
||||
Nerdyninja
|
||||
Nick Eldrenkamp
|
||||
Nik Rudenko
|
||||
Noel Billig
|
||||
ozrk
|
||||
|
@ -450,7 +457,6 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Patrick Nafarrete
|
||||
Paul Black
|
||||
Paul Gieske
|
||||
Paul Mozet
|
||||
Pete
|
||||
Phoenix Jauregui
|
||||
Pierre Caye
|
||||
|
@ -462,7 +468,6 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
Raghava Kovvali
|
||||
Ragnar Pettersson
|
||||
Rammeow
|
||||
Rebecca H
|
||||
Richard Hayes
|
||||
Riley
|
||||
RobotCritter
|
||||
|
@ -508,7 +513,7 @@ generous deed immortalized in the next stable release of Godot Engine.
|
|||
ケルベロス
|
||||
貴宏 小松
|
||||
|
||||
And 181 anonymous donors
|
||||
And 176 anonymous donors
|
||||
|
||||
## Silver and bronze donors
|
||||
|
||||
|
|
64
SConstruct
64
SConstruct
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
EnsureSConsVersion(3, 1, 2)
|
||||
EnsurePythonVersion(3, 6)
|
||||
|
@ -298,7 +299,6 @@ opts.Add(BoolVariable("builtin_pcre2_with_jit", "Use JIT compiler for the built-
|
|||
opts.Add(BoolVariable("builtin_recastnavigation", "Use the built-in Recast navigation library", True))
|
||||
opts.Add(BoolVariable("builtin_rvo2_2d", "Use the built-in RVO2 2D library", True))
|
||||
opts.Add(BoolVariable("builtin_rvo2_3d", "Use the built-in RVO2 3D library", True))
|
||||
opts.Add(BoolVariable("builtin_squish", "Use the built-in squish library", True))
|
||||
opts.Add(BoolVariable("builtin_xatlas", "Use the built-in xatlas library", True))
|
||||
opts.Add(BoolVariable("builtin_zlib", "Use the built-in zlib library", True))
|
||||
opts.Add(BoolVariable("builtin_zstd", "Use the built-in Zstd library", True))
|
||||
|
@ -639,25 +639,18 @@ if env.dev_build:
|
|||
print("NOTE: Developer build, with debug optimization level and debug symbols (unless overridden).")
|
||||
|
||||
# Enforce our minimal compiler version requirements
|
||||
cc_version = methods.get_compiler_version(env) or {
|
||||
"major": None,
|
||||
"minor": None,
|
||||
"patch": None,
|
||||
"metadata1": None,
|
||||
"metadata2": None,
|
||||
"date": None,
|
||||
}
|
||||
cc_version_major = int(cc_version["major"] or -1)
|
||||
cc_version_minor = int(cc_version["minor"] or -1)
|
||||
cc_version_metadata1 = cc_version["metadata1"] or ""
|
||||
cc_version = methods.get_compiler_version(env)
|
||||
cc_version_major = cc_version["major"]
|
||||
cc_version_minor = cc_version["minor"]
|
||||
cc_version_metadata1 = cc_version["metadata1"]
|
||||
|
||||
if methods.using_gcc(env):
|
||||
if cc_version_major == -1:
|
||||
print_warning(
|
||||
"Couldn't detect compiler version, skipping version checks. "
|
||||
"Build may fail if the compiler doesn't support C++17 fully."
|
||||
)
|
||||
elif cc_version_major < 9:
|
||||
elif methods.using_gcc(env):
|
||||
if cc_version_major < 9:
|
||||
print_error(
|
||||
"Detected GCC version older than 9, which does not fully support "
|
||||
"C++17, or has bugs when compiling Godot. Supported versions are 9 "
|
||||
|
@ -677,17 +670,12 @@ if methods.using_gcc(env):
|
|||
print_warning("GCC < 8 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.")
|
||||
env["debug_paths_relative"] = False
|
||||
elif methods.using_clang(env):
|
||||
if cc_version_major == -1:
|
||||
print_warning(
|
||||
"Couldn't detect compiler version, skipping version checks. "
|
||||
"Build may fail if the compiler doesn't support C++17 fully."
|
||||
)
|
||||
# Apple LLVM versions differ from upstream LLVM version \o/, compare
|
||||
# in https://en.wikipedia.org/wiki/Xcode#Toolchain_versions
|
||||
elif env["platform"] == "macos" or env["platform"] == "ios":
|
||||
if env["platform"] == "macos" or env["platform"] == "ios":
|
||||
vanilla = methods.is_vanilla_clang(env)
|
||||
if vanilla and cc_version_major < 6:
|
||||
print_warning(
|
||||
print_error(
|
||||
"Detected Clang version older than 6, which does not fully support "
|
||||
"C++17. Supported versions are Clang 6 and later."
|
||||
)
|
||||
|
@ -712,6 +700,28 @@ elif methods.using_clang(env):
|
|||
if env["debug_paths_relative"] and cc_version_major < 10:
|
||||
print_warning("Clang < 10 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.")
|
||||
env["debug_paths_relative"] = False
|
||||
elif env.msvc:
|
||||
# Ensure latest minor builds of Visual Studio 2017/2019.
|
||||
# https://github.com/godotengine/godot/pull/94995#issuecomment-2336464574
|
||||
if cc_version_major == 16 and cc_version_minor < 11:
|
||||
print_error(
|
||||
"Detected Visual Studio 2019 version older than 16.11, which has bugs "
|
||||
"when compiling Godot. Use a newer VS2019 version, or VS2022."
|
||||
)
|
||||
Exit(255)
|
||||
if cc_version_major == 15 and cc_version_minor < 9:
|
||||
print_error(
|
||||
"Detected Visual Studio 2017 version older than 15.9, which has bugs "
|
||||
"when compiling Godot. Use a newer VS2017 version, or VS2019/VS2022."
|
||||
)
|
||||
Exit(255)
|
||||
if cc_version_major < 15:
|
||||
print_error(
|
||||
"Detected Visual Studio 2015 or earlier, which is unsupported in Godot. "
|
||||
"Supported versions are Visual Studio 2017 and later."
|
||||
)
|
||||
Exit(255)
|
||||
|
||||
|
||||
# Set optimize and debug_symbols flags.
|
||||
# "custom" means do nothing and let users set their own optimization flags.
|
||||
|
@ -789,13 +799,17 @@ if env["lto"] != "none":
|
|||
# This needs to come after `configure`, otherwise we don't have env.msvc.
|
||||
if not env.msvc:
|
||||
# Specifying GNU extensions support explicitly, which are supported by
|
||||
# both GCC and Clang. Both currently default to gnu11 and gnu++14.
|
||||
# both GCC and Clang. Both currently default to gnu11 and gnu++17.
|
||||
env.Prepend(CFLAGS=["-std=gnu11"])
|
||||
env.Prepend(CXXFLAGS=["-std=gnu++17"])
|
||||
else:
|
||||
# MSVC doesn't have clear C standard support, /std only covers C++.
|
||||
# We apply it to CCFLAGS (both C and C++ code) in case it impacts C features.
|
||||
env.Prepend(CCFLAGS=["/std:c++17"])
|
||||
# MSVC started offering C standard support with Visual Studio 2019 16.8, which covers all
|
||||
# of our supported VS2019 & VS2022 versions; VS2017 will only pass the C++ standard.
|
||||
env.Prepend(CXXFLAGS=["/std:c++17"])
|
||||
if cc_version_major < 16:
|
||||
print_warning("Visual Studio 2017 cannot specify a C-Standard.")
|
||||
else:
|
||||
env.Prepend(CFLAGS=["/std:c11"])
|
||||
# MSVC is non-conforming with the C++ standard by default, so we enable more conformance.
|
||||
# Note that this is still not complete conformance, as certain Windows-related headers
|
||||
# don't compile under complete conformance.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -267,6 +267,14 @@ bool Engine::is_extra_gpu_memory_tracking_enabled() const {
|
|||
return extra_gpu_memory_tracking;
|
||||
}
|
||||
|
||||
void Engine::set_print_to_stdout(bool p_enabled) {
|
||||
CoreGlobals::print_line_enabled = p_enabled;
|
||||
}
|
||||
|
||||
bool Engine::is_printing_to_stdout() const {
|
||||
return CoreGlobals::print_line_enabled;
|
||||
}
|
||||
|
||||
void Engine::set_print_error_messages(bool p_enabled) {
|
||||
CoreGlobals::print_error_enabled = p_enabled;
|
||||
}
|
||||
|
|
|
@ -128,6 +128,9 @@ public:
|
|||
void set_time_scale(double p_scale);
|
||||
double get_time_scale() const;
|
||||
|
||||
void set_print_to_stdout(bool p_enabled);
|
||||
bool is_printing_to_stdout() const;
|
||||
|
||||
void set_print_error_messages(bool p_enabled);
|
||||
bool is_printing_error_messages() const;
|
||||
void print_header(const String &p_string) const;
|
||||
|
|
|
@ -1016,7 +1016,7 @@ Error ProjectSettings::save_custom(const String &p_path, const CustomMap &p_cust
|
|||
}
|
||||
}
|
||||
// Check for the existence of a csproj file.
|
||||
if (_csproj_exists(p_path.get_base_dir())) {
|
||||
if (_csproj_exists(get_resource_path())) {
|
||||
// If there is a csproj file, add the C# feature if it doesn't already exist.
|
||||
if (!project_features.has("C#")) {
|
||||
project_features.append("C#");
|
||||
|
@ -1574,6 +1574,7 @@ ProjectSettings::ProjectSettings() {
|
|||
|
||||
ProjectSettings::ProjectSettings(const String &p_path) {
|
||||
if (load_custom(p_path) == OK) {
|
||||
resource_path = p_path.get_base_dir();
|
||||
project_loaded = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -184,6 +184,10 @@ void ResourceSaver::remove_resource_format_saver(Ref<ResourceFormatSaver> p_form
|
|||
::ResourceSaver::remove_resource_format_saver(p_format_saver);
|
||||
}
|
||||
|
||||
ResourceUID::ID ResourceSaver::get_resource_id_for_path(const String &p_path, bool p_generate) {
|
||||
return ::ResourceSaver::get_resource_id_for_path(p_path, p_generate);
|
||||
}
|
||||
|
||||
ResourceSaver *ResourceSaver::singleton = nullptr;
|
||||
|
||||
void ResourceSaver::_bind_methods() {
|
||||
|
@ -191,6 +195,7 @@ void ResourceSaver::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_recognized_extensions", "type"), &ResourceSaver::get_recognized_extensions);
|
||||
ClassDB::bind_method(D_METHOD("add_resource_format_saver", "format_saver", "at_front"), &ResourceSaver::add_resource_format_saver, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("remove_resource_format_saver", "format_saver"), &ResourceSaver::remove_resource_format_saver);
|
||||
ClassDB::bind_method(D_METHOD("get_resource_id_for_path", "path", "generate"), &ResourceSaver::get_resource_id_for_path, DEFVAL(false));
|
||||
|
||||
BIND_BITFIELD_FLAG(FLAG_NONE);
|
||||
BIND_BITFIELD_FLAG(FLAG_RELATIVE_PATHS);
|
||||
|
@ -1419,6 +1424,11 @@ Variant ClassDB::instantiate(const StringName &p_class) const {
|
|||
}
|
||||
}
|
||||
|
||||
ClassDB::APIType ClassDB::class_get_api_type(const StringName &p_class) const {
|
||||
::ClassDB::APIType api_type = ::ClassDB::get_api_type(p_class);
|
||||
return (APIType)api_type;
|
||||
}
|
||||
|
||||
bool ClassDB::class_has_signal(const StringName &p_class, const StringName &p_signal) const {
|
||||
return ::ClassDB::has_signal(p_class, p_signal);
|
||||
}
|
||||
|
@ -1615,7 +1625,7 @@ void ClassDB::get_argument_options(const StringName &p_function, int p_idx, List
|
|||
pf == "class_has_method" || pf == "class_get_method_list" ||
|
||||
pf == "class_get_integer_constant_list" || pf == "class_has_integer_constant" || pf == "class_get_integer_constant" ||
|
||||
pf == "class_has_enum" || pf == "class_get_enum_list" || pf == "class_get_enum_constants" || pf == "class_get_integer_constant_enum" ||
|
||||
pf == "is_class_enabled" || pf == "is_class_enum_bitfield");
|
||||
pf == "is_class_enabled" || pf == "is_class_enum_bitfield" || pf == "class_get_api_type");
|
||||
}
|
||||
if (first_argument_is_class || pf == "is_parent_class") {
|
||||
for (const String &E : get_class_list()) {
|
||||
|
@ -1636,6 +1646,8 @@ void ClassDB::_bind_methods() {
|
|||
::ClassDB::bind_method(D_METHOD("can_instantiate", "class"), &ClassDB::can_instantiate);
|
||||
::ClassDB::bind_method(D_METHOD("instantiate", "class"), &ClassDB::instantiate);
|
||||
|
||||
::ClassDB::bind_method(D_METHOD("class_get_api_type", "class"), &ClassDB::class_get_api_type);
|
||||
|
||||
::ClassDB::bind_method(D_METHOD("class_has_signal", "class", "signal"), &ClassDB::class_has_signal);
|
||||
::ClassDB::bind_method(D_METHOD("class_get_signal", "class", "signal"), &ClassDB::class_get_signal);
|
||||
::ClassDB::bind_method(D_METHOD("class_get_signal_list", "class", "no_inheritance"), &ClassDB::class_get_signal_list, DEFVAL(false));
|
||||
|
@ -1669,6 +1681,12 @@ void ClassDB::_bind_methods() {
|
|||
::ClassDB::bind_method(D_METHOD("is_class_enum_bitfield", "class", "enum", "no_inheritance"), &ClassDB::is_class_enum_bitfield, DEFVAL(false));
|
||||
|
||||
::ClassDB::bind_method(D_METHOD("is_class_enabled", "class"), &ClassDB::is_class_enabled);
|
||||
|
||||
BIND_ENUM_CONSTANT(API_CORE);
|
||||
BIND_ENUM_CONSTANT(API_EDITOR);
|
||||
BIND_ENUM_CONSTANT(API_EXTENSION);
|
||||
BIND_ENUM_CONSTANT(API_EDITOR_EXTENSION);
|
||||
BIND_ENUM_CONSTANT(API_NONE);
|
||||
}
|
||||
|
||||
} // namespace special
|
||||
|
@ -1835,6 +1853,14 @@ String Engine::get_write_movie_path() const {
|
|||
return ::Engine::get_singleton()->get_write_movie_path();
|
||||
}
|
||||
|
||||
void Engine::set_print_to_stdout(bool p_enabled) {
|
||||
::Engine::get_singleton()->set_print_to_stdout(p_enabled);
|
||||
}
|
||||
|
||||
bool Engine::is_printing_to_stdout() const {
|
||||
return ::Engine::get_singleton()->is_printing_to_stdout();
|
||||
}
|
||||
|
||||
void Engine::set_print_error_messages(bool p_enabled) {
|
||||
::Engine::get_singleton()->set_print_error_messages(p_enabled);
|
||||
}
|
||||
|
@ -1903,10 +1929,14 @@ void Engine::_bind_methods() {
|
|||
|
||||
ClassDB::bind_method(D_METHOD("get_write_movie_path"), &Engine::get_write_movie_path);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_print_to_stdout", "enabled"), &Engine::set_print_to_stdout);
|
||||
ClassDB::bind_method(D_METHOD("is_printing_to_stdout"), &Engine::is_printing_to_stdout);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_print_error_messages", "enabled"), &Engine::set_print_error_messages);
|
||||
ClassDB::bind_method(D_METHOD("is_printing_error_messages"), &Engine::is_printing_error_messages);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "print_error_messages"), "set_print_error_messages", "is_printing_error_messages");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "print_to_stdout"), "set_print_to_stdout", "is_printing_to_stdout");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "physics_ticks_per_second"), "set_physics_ticks_per_second", "get_physics_ticks_per_second");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_physics_steps_per_frame"), "set_max_physics_steps_per_frame", "get_max_physics_steps_per_frame");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_fps"), "set_max_fps", "get_max_fps");
|
||||
|
|
|
@ -116,6 +116,8 @@ public:
|
|||
void add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front);
|
||||
void remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver);
|
||||
|
||||
ResourceUID::ID get_resource_id_for_path(const String &p_path, bool p_generate = false);
|
||||
|
||||
ResourceSaver() { singleton = this; }
|
||||
};
|
||||
|
||||
|
@ -447,6 +449,14 @@ protected:
|
|||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
enum APIType {
|
||||
API_CORE,
|
||||
API_EDITOR,
|
||||
API_EXTENSION,
|
||||
API_EDITOR_EXTENSION,
|
||||
API_NONE,
|
||||
};
|
||||
|
||||
PackedStringArray get_class_list() const;
|
||||
PackedStringArray get_inheriters_from_class(const StringName &p_class) const;
|
||||
StringName get_parent_class(const StringName &p_class) const;
|
||||
|
@ -455,6 +465,7 @@ public:
|
|||
bool can_instantiate(const StringName &p_class) const;
|
||||
Variant instantiate(const StringName &p_class) const;
|
||||
|
||||
APIType class_get_api_type(const StringName &p_class) const;
|
||||
bool class_has_signal(const StringName &p_class, const StringName &p_signal) const;
|
||||
Dictionary class_get_signal(const StringName &p_class, const StringName &p_signal) const;
|
||||
TypedArray<Dictionary> class_get_signal_list(const StringName &p_class, bool p_no_inheritance = false) const;
|
||||
|
@ -558,6 +569,9 @@ public:
|
|||
// `set_write_movie_path()` is not exposed to the scripting API as changing it at run-time has no effect.
|
||||
String get_write_movie_path() const;
|
||||
|
||||
void set_print_to_stdout(bool p_enabled);
|
||||
bool is_printing_to_stdout() const;
|
||||
|
||||
void set_print_error_messages(bool p_enabled);
|
||||
bool is_printing_error_messages() const;
|
||||
|
||||
|
@ -634,4 +648,6 @@ VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyEndType);
|
|||
|
||||
VARIANT_ENUM_CAST(core_bind::Thread::Priority);
|
||||
|
||||
VARIANT_ENUM_CAST(core_bind::special::ClassDB::APIType);
|
||||
|
||||
#endif // CORE_BIND_H
|
||||
|
|
|
@ -677,6 +677,7 @@ void register_global_constants() {
|
|||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NODE_TYPE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_HIDE_QUATERNION_EDIT);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PASSWORD);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_TOOL_BUTTON);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX);
|
||||
|
||||
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NONE);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -1017,6 +1017,7 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
|
|||
d2["name"] = String(method_name);
|
||||
d2["is_const"] = (F.flags & METHOD_FLAG_CONST) ? true : false;
|
||||
d2["is_static"] = (F.flags & METHOD_FLAG_STATIC) ? true : false;
|
||||
d2["is_required"] = (F.flags & METHOD_FLAG_VIRTUAL_REQUIRED) ? true : false;
|
||||
d2["is_vararg"] = false;
|
||||
d2["is_virtual"] = true;
|
||||
// virtual functions have no hash since no MethodBind is involved
|
||||
|
|
|
@ -55,10 +55,10 @@ def generate_mod_version(argcount, const=False, returns=False):
|
|||
|
||||
proto_ex = """
|
||||
#define EXBIND$VER($RETTYPE m_name$ARG) \\
|
||||
GDVIRTUAL$VER($RETTYPE_##m_name$ARG)\\
|
||||
GDVIRTUAL$VER_REQUIRED($RETTYPE_##m_name$ARG)\\
|
||||
virtual $RETVAL m_name($FUNCARGS) $CONST override { \\
|
||||
$RETPRE\\
|
||||
GDVIRTUAL_REQUIRED_CALL(_##m_name$CALLARGS$RETREF);\\
|
||||
GDVIRTUAL_CALL(_##m_name$CALLARGS$RETREF);\\
|
||||
$RETPOST\\
|
||||
}
|
||||
"""
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ def make_default_controller_mappings(target, source, env):
|
|||
guid = line_parts[0]
|
||||
if guid in platform_mappings[current_platform]:
|
||||
g.write(
|
||||
"// WARNING - DATABASE {} OVERWROTE PRIOR MAPPING: {} {}\n".format(
|
||||
"// WARNING: DATABASE {} OVERWROTE PRIOR MAPPING: {} {}\n".format(
|
||||
src_path, current_platform, platform_mappings[current_platform][guid]
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1088,7 +1088,7 @@ void InputEventMouseMotion::_bind_methods() {
|
|||
///////////////////////////////////
|
||||
|
||||
void InputEventJoypadMotion::set_axis(JoyAxis p_axis) {
|
||||
ERR_FAIL_COND(p_axis < JoyAxis::LEFT_X || p_axis > JoyAxis::MAX);
|
||||
ERR_FAIL_COND(p_axis < JoyAxis::INVALID || p_axis > JoyAxis::MAX);
|
||||
|
||||
axis = p_axis;
|
||||
emit_changed();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -102,6 +102,22 @@ void PackedData::add_pack_source(PackSource *p_source) {
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t *PackedData::get_file_hash(const String &p_path) {
|
||||
PathMD5 pmd5(p_path.md5_buffer());
|
||||
HashMap<PathMD5, PackedFile, PathMD5>::Iterator E = files.find(pmd5);
|
||||
if (!E || E->value.offset == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return E->value.md5;
|
||||
}
|
||||
|
||||
void PackedData::clear() {
|
||||
files.clear();
|
||||
_free_packed_dirs(root);
|
||||
root = memnew(PackedDir);
|
||||
}
|
||||
|
||||
PackedData *PackedData::singleton = nullptr;
|
||||
|
||||
PackedData::PackedData() {
|
||||
|
|
|
@ -111,6 +111,7 @@ private:
|
|||
public:
|
||||
void add_pack_source(PackSource *p_source);
|
||||
void add_path(const String &p_pkg_path, const String &p_path, uint64_t p_ofs, uint64_t p_size, const uint8_t *p_md5, PackSource *p_src, bool p_replace_files, bool p_encrypted = false); // for PackSource
|
||||
uint8_t *get_file_hash(const String &p_path);
|
||||
|
||||
void set_disabled(bool p_disabled) { disabled = p_disabled; }
|
||||
_FORCE_INLINE_ bool is_disabled() const { return disabled; }
|
||||
|
@ -118,6 +119,8 @@ public:
|
|||
static PackedData *get_singleton() { return singleton; }
|
||||
Error add_pack(const String &p_path, bool p_replace_files, uint64_t p_offset);
|
||||
|
||||
void clear();
|
||||
|
||||
_FORCE_INLINE_ Ref<FileAccess> try_open_path(const String &p_path);
|
||||
_FORCE_INLINE_ bool has_path(const String &p_path);
|
||||
|
||||
|
|
|
@ -866,12 +866,10 @@ static void _scale_cubic(const uint8_t *__restrict p_src, uint8_t *__restrict p_
|
|||
|
||||
template <int CC, typename T>
|
||||
static void _scale_bilinear(const uint8_t *__restrict p_src, uint8_t *__restrict p_dst, uint32_t p_src_width, uint32_t p_src_height, uint32_t p_dst_width, uint32_t p_dst_height) {
|
||||
enum {
|
||||
FRAC_BITS = 8,
|
||||
FRAC_LEN = (1 << FRAC_BITS),
|
||||
FRAC_HALF = (FRAC_LEN >> 1),
|
||||
FRAC_MASK = FRAC_LEN - 1
|
||||
};
|
||||
constexpr uint32_t FRAC_BITS = 8;
|
||||
constexpr uint32_t FRAC_LEN = (1 << FRAC_BITS);
|
||||
constexpr uint32_t FRAC_HALF = (FRAC_LEN >> 1);
|
||||
constexpr uint32_t FRAC_MASK = FRAC_LEN - 1;
|
||||
|
||||
for (uint32_t i = 0; i < p_dst_height; i++) {
|
||||
// Add 0.5 in order to interpolate based on pixel center
|
||||
|
@ -2751,6 +2749,19 @@ Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels
|
|||
|
||||
} break;
|
||||
|
||||
case COMPRESS_S3TC: {
|
||||
// BC3 is unsupported currently.
|
||||
if ((p_channels == USED_CHANNELS_RGB || p_channels == USED_CHANNELS_L) && _image_compress_bc_rd_func) {
|
||||
Error result = _image_compress_bc_rd_func(this, p_channels);
|
||||
|
||||
// If the image was compressed successfully, we return here. If not, we fall back to the default compression scheme.
|
||||
if (result == OK) {
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
default: {
|
||||
}
|
||||
}
|
||||
|
@ -3138,6 +3149,7 @@ void (*Image::_image_compress_etc1_func)(Image *) = nullptr;
|
|||
void (*Image::_image_compress_etc2_func)(Image *, Image::UsedChannels) = nullptr;
|
||||
void (*Image::_image_compress_astc_func)(Image *, Image::ASTCFormat) = nullptr;
|
||||
Error (*Image::_image_compress_bptc_rd_func)(Image *, Image::UsedChannels) = nullptr;
|
||||
Error (*Image::_image_compress_bc_rd_func)(Image *, Image::UsedChannels) = nullptr;
|
||||
void (*Image::_image_decompress_bc)(Image *) = nullptr;
|
||||
void (*Image::_image_decompress_bptc)(Image *) = nullptr;
|
||||
void (*Image::_image_decompress_etc1)(Image *) = nullptr;
|
||||
|
|
|
@ -160,6 +160,7 @@ public:
|
|||
static void (*_image_compress_astc_func)(Image *, ASTCFormat p_format);
|
||||
|
||||
static Error (*_image_compress_bptc_rd_func)(Image *, UsedChannels p_channels);
|
||||
static Error (*_image_compress_bc_rd_func)(Image *, UsedChannels p_channels);
|
||||
|
||||
static void (*_image_decompress_bc)(Image *);
|
||||
static void (*_image_decompress_bptc)(Image *);
|
||||
|
|
|
@ -299,7 +299,7 @@ Ref<StreamPeer> PacketPeerStream::get_stream_peer() const {
|
|||
|
||||
void PacketPeerStream::set_input_buffer_max_size(int p_max_size) {
|
||||
ERR_FAIL_COND_MSG(p_max_size < 0, "Max size of input buffer size cannot be smaller than 0.");
|
||||
//warning may lose packets
|
||||
// WARNING: May lose packets.
|
||||
ERR_FAIL_COND_MSG(ring_buffer.data_left(), "Buffer in use, resizing would cause loss of data.");
|
||||
ring_buffer.resize(nearest_shift(next_power_of_2(p_max_size + 4)) - 1);
|
||||
input_buffer.resize(next_power_of_2(p_max_size + 4));
|
||||
|
|
|
@ -47,12 +47,12 @@ static int _get_pad(int p_alignment, int p_n) {
|
|||
}
|
||||
|
||||
void PCKPacker::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("pck_start", "pck_name", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(32), DEFVAL("0000000000000000000000000000000000000000000000000000000000000000"), DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("pck_start", "pck_path", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(32), DEFVAL("0000000000000000000000000000000000000000000000000000000000000000"), DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("add_file", "pck_path", "source_path", "encrypt"), &PCKPacker::add_file, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("flush", "verbose"), &PCKPacker::flush, DEFVAL(false));
|
||||
}
|
||||
|
||||
Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &p_key, bool p_encrypt_directory) {
|
||||
Error PCKPacker::pck_start(const String &p_pck_path, int p_alignment, const String &p_key, bool p_encrypt_directory) {
|
||||
ERR_FAIL_COND_V_MSG((p_key.is_empty() || !p_key.is_valid_hex_number(false) || p_key.length() != 64), ERR_CANT_CREATE, "Invalid Encryption Key (must be 64 characters long).");
|
||||
ERR_FAIL_COND_V_MSG(p_alignment <= 0, ERR_CANT_CREATE, "Invalid alignment, must be greater then 0.");
|
||||
|
||||
|
@ -83,8 +83,8 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &
|
|||
}
|
||||
enc_dir = p_encrypt_directory;
|
||||
|
||||
file = FileAccess::open(p_file, FileAccess::WRITE);
|
||||
ERR_FAIL_COND_V_MSG(file.is_null(), ERR_CANT_CREATE, "Can't open file to write: " + String(p_file) + ".");
|
||||
file = FileAccess::open(p_pck_path, FileAccess::WRITE);
|
||||
ERR_FAIL_COND_V_MSG(file.is_null(), ERR_CANT_CREATE, "Can't open file to write: " + String(p_pck_path) + ".");
|
||||
|
||||
alignment = p_alignment;
|
||||
|
||||
|
@ -106,7 +106,7 @@ Error PCKPacker::pck_start(const String &p_file, int p_alignment, const String &
|
|||
return OK;
|
||||
}
|
||||
|
||||
Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encrypt) {
|
||||
Error PCKPacker::add_file(const String &p_pck_path, const String &p_src, bool p_encrypt) {
|
||||
ERR_FAIL_COND_V_MSG(file.is_null(), ERR_INVALID_PARAMETER, "File must be opened before use.");
|
||||
|
||||
Ref<FileAccess> f = FileAccess::open(p_src, FileAccess::READ);
|
||||
|
@ -117,7 +117,7 @@ Error PCKPacker::add_file(const String &p_file, const String &p_src, bool p_encr
|
|||
File pf;
|
||||
// Simplify path here and on every 'files' access so that paths that have extra '/'
|
||||
// symbols in them still match to the MD5 hash for the saved path.
|
||||
pf.path = p_file.simplify_path();
|
||||
pf.path = p_pck_path.simplify_path();
|
||||
pf.src_path = p_src;
|
||||
pf.ofs = ofs;
|
||||
pf.size = f->get_length();
|
||||
|
|
|
@ -58,8 +58,8 @@ class PCKPacker : public RefCounted {
|
|||
Vector<File> files;
|
||||
|
||||
public:
|
||||
Error pck_start(const String &p_file, int p_alignment = 32, const String &p_key = "0000000000000000000000000000000000000000000000000000000000000000", bool p_encrypt_directory = false);
|
||||
Error add_file(const String &p_file, const String &p_src, bool p_encrypt = false);
|
||||
Error pck_start(const String &p_pck_path, int p_alignment = 32, const String &p_key = "0000000000000000000000000000000000000000000000000000000000000000", bool p_encrypt_directory = false);
|
||||
Error add_file(const String &p_pck_path, const String &p_src, bool p_encrypt = false);
|
||||
Error flush(bool p_verbose = false);
|
||||
|
||||
PCKPacker() {}
|
||||
|
|
|
@ -96,6 +96,7 @@ String Resource::get_path() const {
|
|||
|
||||
void Resource::set_path_cache(const String &p_path) {
|
||||
path_cache = p_path;
|
||||
GDVIRTUAL_CALL(_set_path_cache, p_path);
|
||||
}
|
||||
|
||||
String Resource::generate_scene_unique_id() {
|
||||
|
@ -188,6 +189,7 @@ void Resource::disconnect_changed(const Callable &p_callable) {
|
|||
}
|
||||
|
||||
void Resource::reset_state() {
|
||||
GDVIRTUAL_CALL(_reset_state);
|
||||
}
|
||||
|
||||
Error Resource::copy_from(const Ref<Resource> &p_resource) {
|
||||
|
@ -495,9 +497,9 @@ void Resource::set_as_translation_remapped(bool p_remapped) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
//helps keep IDs same number when loading/saving scenes. -1 clears ID and it Returns -1 when no id stored
|
||||
void Resource::set_id_for_path(const String &p_path, const String &p_id) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (p_id.is_empty()) {
|
||||
ResourceCache::path_cache_lock.write_lock();
|
||||
ResourceCache::resource_path_cache[p_path].erase(get_path());
|
||||
|
@ -507,9 +509,11 @@ void Resource::set_id_for_path(const String &p_path, const String &p_id) {
|
|||
ResourceCache::resource_path_cache[p_path][get_path()] = p_id;
|
||||
ResourceCache::path_cache_lock.write_unlock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
String Resource::get_id_for_path(const String &p_path) const {
|
||||
#ifdef TOOLS_ENABLED
|
||||
ResourceCache::path_cache_lock.read_lock();
|
||||
if (ResourceCache::resource_path_cache[p_path].has(get_path())) {
|
||||
String result = ResourceCache::resource_path_cache[p_path][get_path()];
|
||||
|
@ -519,13 +523,16 @@ String Resource::get_id_for_path(const String &p_path) const {
|
|||
ResourceCache::path_cache_lock.read_unlock();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
void Resource::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_path", "path"), &Resource::_set_path);
|
||||
ClassDB::bind_method(D_METHOD("take_over_path", "path"), &Resource::_take_over_path);
|
||||
ClassDB::bind_method(D_METHOD("get_path"), &Resource::get_path);
|
||||
ClassDB::bind_method(D_METHOD("set_path_cache", "path"), &Resource::set_path_cache);
|
||||
ClassDB::bind_method(D_METHOD("set_name", "name"), &Resource::set_name);
|
||||
ClassDB::bind_method(D_METHOD("get_name"), &Resource::get_name);
|
||||
ClassDB::bind_method(D_METHOD("get_rid"), &Resource::get_rid);
|
||||
|
@ -533,6 +540,12 @@ void Resource::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("is_local_to_scene"), &Resource::is_local_to_scene);
|
||||
ClassDB::bind_method(D_METHOD("get_local_scene"), &Resource::get_local_scene);
|
||||
ClassDB::bind_method(D_METHOD("setup_local_to_scene"), &Resource::setup_local_to_scene);
|
||||
ClassDB::bind_method(D_METHOD("reset_state"), &Resource::reset_state);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_id_for_path", "path", "id"), &Resource::set_id_for_path);
|
||||
ClassDB::bind_method(D_METHOD("get_id_for_path", "path"), &Resource::get_id_for_path);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_built_in"), &Resource::is_built_in);
|
||||
|
||||
ClassDB::bind_static_method("Resource", D_METHOD("generate_scene_unique_id"), &Resource::generate_scene_unique_id);
|
||||
ClassDB::bind_method(D_METHOD("set_scene_unique_id", "id"), &Resource::set_scene_unique_id);
|
||||
|
@ -552,6 +565,8 @@ void Resource::_bind_methods() {
|
|||
|
||||
GDVIRTUAL_BIND(_setup_local_to_scene);
|
||||
GDVIRTUAL_BIND(_get_rid);
|
||||
GDVIRTUAL_BIND(_reset_state);
|
||||
GDVIRTUAL_BIND(_set_path_cache, "path");
|
||||
}
|
||||
|
||||
Resource::Resource() :
|
||||
|
|
|
@ -89,6 +89,9 @@ protected:
|
|||
|
||||
GDVIRTUAL0RC(RID, _get_rid);
|
||||
|
||||
GDVIRTUAL1C(_set_path_cache, String);
|
||||
GDVIRTUAL0(_reset_state);
|
||||
|
||||
public:
|
||||
static Node *(*_get_local_scene_func)(); //used by editor
|
||||
static void (*_update_configuration_warning)(); //used by editor
|
||||
|
@ -144,11 +147,9 @@ public:
|
|||
|
||||
virtual RID get_rid() const; // some resources may offer conversion to RID
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
//helps keep IDs same number when loading/saving scenes. -1 clears ID and it Returns -1 when no id stored
|
||||
void set_id_for_path(const String &p_path, const String &p_id);
|
||||
String get_id_for_path(const String &p_path) const;
|
||||
#endif
|
||||
|
||||
Resource();
|
||||
~Resource();
|
||||
|
|
|
@ -507,7 +507,7 @@ bool ResourceFormatImporter::are_import_settings_valid(const String &p_path) con
|
|||
|
||||
for (int i = 0; i < importers.size(); i++) {
|
||||
if (importers[i]->get_importer_name() == pat.importer) {
|
||||
if (!importers[i]->are_import_settings_valid(p_path)) { //importer thinks this is not valid
|
||||
if (!importers[i]->are_import_settings_valid(p_path, pat.metadata)) { //importer thinks this is not valid
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ public:
|
|||
virtual void import_threaded_end() {}
|
||||
|
||||
virtual Error import_group_file(const String &p_group_file, const HashMap<String, HashMap<StringName, Variant>> &p_source_file_options, const HashMap<String, String> &p_base_paths) { return ERR_UNAVAILABLE; }
|
||||
virtual bool are_import_settings_valid(const String &p_path) const { return true; }
|
||||
virtual bool are_import_settings_valid(const String &p_path, const Dictionary &p_meta) const { return true; }
|
||||
virtual String get_import_settings_string() const { return String(); }
|
||||
};
|
||||
|
||||
|
|
|
@ -303,10 +303,6 @@ Ref<Resource> ResourceLoader::_load(const String &p_path, const String &p_origin
|
|||
return res;
|
||||
}
|
||||
|
||||
if (r_error) {
|
||||
*r_error = ERR_FILE_UNRECOGNIZED;
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V_MSG(found, Ref<Resource>(),
|
||||
vformat("Failed loading resource: %s. Make sure resources have been imported by opening the project in the editor at least once.", p_path));
|
||||
|
||||
|
@ -860,7 +856,7 @@ Ref<Resource> ResourceLoader::_load_complete_inner(LoadToken &p_load_token, Erro
|
|||
}
|
||||
}
|
||||
core_bind::Semaphore done;
|
||||
MessageQueue::get_main_singleton()->push_callable(callable_mp(&done, &core_bind::Semaphore::post));
|
||||
MessageQueue::get_main_singleton()->push_callable(callable_mp(&done, &core_bind::Semaphore::post).bind(1));
|
||||
done.wait();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -319,11 +319,11 @@ Vector3 AStar3D::get_closest_position_in_segment(const Vector3 &p_point) const {
|
|||
return closest_point;
|
||||
}
|
||||
|
||||
bool AStar3D::_solve(Point *begin_point, Point *end_point) {
|
||||
bool AStar3D::_solve(Point *begin_point, Point *end_point, bool p_allow_partial_path) {
|
||||
last_closest_point = nullptr;
|
||||
pass++;
|
||||
|
||||
if (!end_point->enabled) {
|
||||
if (!end_point->enabled && !p_allow_partial_path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -443,7 +443,7 @@ Vector<Vector3> AStar3D::get_point_path(int64_t p_from_id, int64_t p_to_id, bool
|
|||
Point *begin_point = a;
|
||||
Point *end_point = b;
|
||||
|
||||
bool found_route = _solve(begin_point, end_point);
|
||||
bool found_route = _solve(begin_point, end_point, p_allow_partial_path);
|
||||
if (!found_route) {
|
||||
if (!p_allow_partial_path || last_closest_point == nullptr) {
|
||||
return Vector<Vector3>();
|
||||
|
@ -497,7 +497,7 @@ Vector<int64_t> AStar3D::get_id_path(int64_t p_from_id, int64_t p_to_id, bool p_
|
|||
Point *begin_point = a;
|
||||
Point *end_point = b;
|
||||
|
||||
bool found_route = _solve(begin_point, end_point);
|
||||
bool found_route = _solve(begin_point, end_point, p_allow_partial_path);
|
||||
if (!found_route) {
|
||||
if (!p_allow_partial_path || last_closest_point == nullptr) {
|
||||
return Vector<int64_t>();
|
||||
|
@ -726,7 +726,7 @@ Vector<Vector2> AStar2D::get_point_path(int64_t p_from_id, int64_t p_to_id, bool
|
|||
AStar3D::Point *begin_point = a;
|
||||
AStar3D::Point *end_point = b;
|
||||
|
||||
bool found_route = _solve(begin_point, end_point);
|
||||
bool found_route = _solve(begin_point, end_point, p_allow_partial_path);
|
||||
if (!found_route) {
|
||||
if (!p_allow_partial_path || astar.last_closest_point == nullptr) {
|
||||
return Vector<Vector2>();
|
||||
|
@ -780,7 +780,7 @@ Vector<int64_t> AStar2D::get_id_path(int64_t p_from_id, int64_t p_to_id, bool p_
|
|||
AStar3D::Point *begin_point = a;
|
||||
AStar3D::Point *end_point = b;
|
||||
|
||||
bool found_route = _solve(begin_point, end_point);
|
||||
bool found_route = _solve(begin_point, end_point, p_allow_partial_path);
|
||||
if (!found_route) {
|
||||
if (!p_allow_partial_path || astar.last_closest_point == nullptr) {
|
||||
return Vector<int64_t>();
|
||||
|
@ -816,11 +816,11 @@ Vector<int64_t> AStar2D::get_id_path(int64_t p_from_id, int64_t p_to_id, bool p_
|
|||
return path;
|
||||
}
|
||||
|
||||
bool AStar2D::_solve(AStar3D::Point *begin_point, AStar3D::Point *end_point) {
|
||||
bool AStar2D::_solve(AStar3D::Point *begin_point, AStar3D::Point *end_point, bool p_allow_partial_path) {
|
||||
astar.last_closest_point = nullptr;
|
||||
astar.pass++;
|
||||
|
||||
if (!end_point->enabled) {
|
||||
if (!end_point->enabled && !p_allow_partial_path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ class AStar3D : public RefCounted {
|
|||
HashSet<Segment, Segment> segments;
|
||||
Point *last_closest_point = nullptr;
|
||||
|
||||
bool _solve(Point *begin_point, Point *end_point);
|
||||
bool _solve(Point *begin_point, Point *end_point, bool p_allow_partial_path);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
@ -171,7 +171,7 @@ class AStar2D : public RefCounted {
|
|||
GDCLASS(AStar2D, RefCounted);
|
||||
AStar3D astar;
|
||||
|
||||
bool _solve(AStar3D::Point *begin_point, AStar3D::Point *end_point);
|
||||
bool _solve(AStar3D::Point *begin_point, AStar3D::Point *end_point, bool p_allow_partial_path);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
|
|
@ -491,11 +491,11 @@ void AStarGrid2D::_get_nbors(Point *p_point, LocalVector<Point *> &r_nbors) {
|
|||
}
|
||||
}
|
||||
|
||||
bool AStarGrid2D::_solve(Point *p_begin_point, Point *p_end_point) {
|
||||
bool AStarGrid2D::_solve(Point *p_begin_point, Point *p_end_point, bool p_allow_partial_path) {
|
||||
last_closest_point = nullptr;
|
||||
pass++;
|
||||
|
||||
if (_get_solid_unchecked(p_end_point->id)) {
|
||||
if (_get_solid_unchecked(p_end_point->id) && !p_allow_partial_path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -647,7 +647,7 @@ Vector<Vector2> AStarGrid2D::get_point_path(const Vector2i &p_from_id, const Vec
|
|||
Point *begin_point = a;
|
||||
Point *end_point = b;
|
||||
|
||||
bool found_route = _solve(begin_point, end_point);
|
||||
bool found_route = _solve(begin_point, end_point, p_allow_partial_path);
|
||||
if (!found_route) {
|
||||
if (!p_allow_partial_path || last_closest_point == nullptr) {
|
||||
return Vector<Vector2>();
|
||||
|
@ -700,7 +700,7 @@ TypedArray<Vector2i> AStarGrid2D::get_id_path(const Vector2i &p_from_id, const V
|
|||
Point *begin_point = a;
|
||||
Point *end_point = b;
|
||||
|
||||
bool found_route = _solve(begin_point, end_point);
|
||||
bool found_route = _solve(begin_point, end_point, p_allow_partial_path);
|
||||
if (!found_route) {
|
||||
if (!p_allow_partial_path || last_closest_point == nullptr) {
|
||||
return TypedArray<Vector2i>();
|
||||
|
|
|
@ -159,8 +159,8 @@ private: // Internal routines.
|
|||
|
||||
void _get_nbors(Point *p_point, LocalVector<Point *> &r_nbors);
|
||||
Point *_jump(Point *p_from, Point *p_to);
|
||||
bool _solve(Point *p_begin_point, Point *p_end_point, bool p_allow_partial_path);
|
||||
Point *_forced_successor(int32_t p_x, int32_t p_y, int32_t p_dx, int32_t p_dy, bool p_inclusive = false);
|
||||
bool _solve(Point *p_begin_point, Point *p_end_point);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
|
|
@ -41,11 +41,11 @@ struct [[nodiscard]] Basis {
|
|||
Vector3(0, 0, 1)
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ const Vector3 &operator[](int p_axis) const {
|
||||
return rows[p_axis];
|
||||
_FORCE_INLINE_ const Vector3 &operator[](int p_row) const {
|
||||
return rows[p_row];
|
||||
}
|
||||
_FORCE_INLINE_ Vector3 &operator[](int p_axis) {
|
||||
return rows[p_axis];
|
||||
_FORCE_INLINE_ Vector3 &operator[](int p_row) {
|
||||
return rows[p_row];
|
||||
}
|
||||
|
||||
void invert();
|
||||
|
|
|
@ -204,7 +204,7 @@ public:
|
|||
static Int128 mul(uint64_t a, uint64_t b);
|
||||
|
||||
Int128 operator-() const {
|
||||
return Int128((uint64_t) - (int64_t)low, ~high + (low == 0));
|
||||
return Int128(uint64_t(-int64_t(low)), ~high + (low == 0));
|
||||
}
|
||||
|
||||
Int128 operator+(const Int128 &b) const {
|
||||
|
|
|
@ -39,16 +39,19 @@
|
|||
class String;
|
||||
|
||||
struct [[nodiscard]] Transform2D {
|
||||
// Warning #1: basis of Transform2D is stored differently from Basis. In terms of columns array, the basis matrix looks like "on paper":
|
||||
// WARNING: The basis of Transform2D is stored differently from Basis.
|
||||
// In terms of columns array, the basis matrix looks like "on paper":
|
||||
// M = (columns[0][0] columns[1][0])
|
||||
// (columns[0][1] columns[1][1])
|
||||
// This is such that the columns, which can be interpreted as basis vectors of the coordinate system "painted" on the object, can be accessed as columns[i].
|
||||
// Note that this is the opposite of the indices in mathematical texts, meaning: $M_{12}$ in a math book corresponds to columns[1][0] here.
|
||||
// This is such that the columns, which can be interpreted as basis vectors
|
||||
// of the coordinate system "painted" on the object, can be accessed as columns[i].
|
||||
// NOTE: This is the opposite of the indices in mathematical texts,
|
||||
// meaning: $M_{12}$ in a math book corresponds to columns[1][0] here.
|
||||
// This requires additional care when working with explicit indices.
|
||||
// See https://en.wikipedia.org/wiki/Row-_and_column-major_order for further reading.
|
||||
|
||||
// Warning #2: 2D be aware that unlike 3D code, 2D code uses a left-handed coordinate system: Y-axis points down,
|
||||
// and angle is measure from +X to +Y in a clockwise-fashion.
|
||||
// WARNING: Be aware that unlike 3D code, 2D code uses a left-handed coordinate system:
|
||||
// Y-axis points down, and angle is measure from +X to +Y in a clockwise-fashion.
|
||||
|
||||
Vector2 columns[3];
|
||||
|
||||
|
|
|
@ -55,16 +55,16 @@ struct [[nodiscard]] Vector4 {
|
|||
real_t z;
|
||||
real_t w;
|
||||
};
|
||||
real_t components[4] = { 0, 0, 0, 0 };
|
||||
real_t coord[4] = { 0, 0, 0, 0 };
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ real_t &operator[](int p_axis) {
|
||||
DEV_ASSERT((unsigned int)p_axis < 4);
|
||||
return components[p_axis];
|
||||
return coord[p_axis];
|
||||
}
|
||||
_FORCE_INLINE_ const real_t &operator[](int p_axis) const {
|
||||
DEV_ASSERT((unsigned int)p_axis < 4);
|
||||
return components[p_axis];
|
||||
return coord[p_axis];
|
||||
}
|
||||
|
||||
Vector4::Axis min_axis_index() const;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#include "core/variant/binder_common.h"
|
||||
#include "core/variant/callable.h"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
class CallableCustomMethodPointerBase : public CallableCustom {
|
||||
uint32_t *comp_ptr = nullptr;
|
||||
uint32_t comp_size;
|
||||
|
@ -77,59 +79,8 @@ public:
|
|||
virtual uint32_t hash() const;
|
||||
};
|
||||
|
||||
template <typename T, typename... P>
|
||||
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
T *instance;
|
||||
uint64_t object_id;
|
||||
void (T::*method)(P...);
|
||||
} data;
|
||||
|
||||
public:
|
||||
virtual ObjectID get_object() const {
|
||||
if (ObjectDB::get_instance(ObjectID(data.object_id)) == nullptr) {
|
||||
return ObjectID();
|
||||
}
|
||||
return data.instance->get_instance_id();
|
||||
}
|
||||
|
||||
virtual int get_argument_count(bool &r_is_valid) const {
|
||||
r_is_valid = true;
|
||||
return sizeof...(P);
|
||||
}
|
||||
|
||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
||||
ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
|
||||
call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error);
|
||||
}
|
||||
|
||||
CallableCustomMethodPointer(T *p_instance, void (T::*p_method)(P...)) {
|
||||
memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
|
||||
data.instance = p_instance;
|
||||
data.object_id = p_instance->get_instance_id();
|
||||
data.method = p_method;
|
||||
_setup((uint32_t *)&data, sizeof(Data));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... P>
|
||||
Callable create_custom_callable_function_pointer(T *p_instance,
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
const char *p_func_text,
|
||||
#endif
|
||||
void (T::*p_method)(P...)) {
|
||||
typedef CallableCustomMethodPointer<T, P...> CCMP; // Messes with memnew otherwise.
|
||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
|
||||
#endif
|
||||
return Callable(ccmp);
|
||||
}
|
||||
|
||||
// VERSION WITH RETURN
|
||||
|
||||
template <typename T, typename R, typename... P>
|
||||
class CallableCustomMethodPointerRet : public CallableCustomMethodPointerBase {
|
||||
class CallableCustomMethodPointer : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
T *instance;
|
||||
uint64_t object_id;
|
||||
|
@ -152,10 +103,14 @@ public:
|
|||
|
||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
||||
ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
|
||||
if constexpr (std::is_same<R, void>::value) {
|
||||
call_with_variant_args(data.instance, data.method, p_arguments, p_argcount, r_call_error);
|
||||
} else {
|
||||
call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||
}
|
||||
}
|
||||
|
||||
CallableCustomMethodPointerRet(T *p_instance, R (T::*p_method)(P...)) {
|
||||
CallableCustomMethodPointer(T *p_instance, R (T::*p_method)(P...)) {
|
||||
memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
|
||||
data.instance = p_instance;
|
||||
data.object_id = p_instance->get_instance_id();
|
||||
|
@ -164,13 +119,13 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T, typename R, typename... P>
|
||||
template <typename T, typename... P>
|
||||
Callable create_custom_callable_function_pointer(T *p_instance,
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
const char *p_func_text,
|
||||
#endif
|
||||
R (T::*p_method)(P...)) {
|
||||
typedef CallableCustomMethodPointerRet<T, R, P...> CCMP; // Messes with memnew otherwise.
|
||||
void (T::*p_method)(P...)) {
|
||||
typedef CallableCustomMethodPointer<T, void, P...> CCMP; // Messes with memnew otherwise.
|
||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
|
||||
|
@ -178,10 +133,24 @@ Callable create_custom_callable_function_pointer(T *p_instance,
|
|||
return Callable(ccmp);
|
||||
}
|
||||
|
||||
// CONST VERSION WITH RETURN
|
||||
template <typename T, typename R, typename... P>
|
||||
Callable create_custom_callable_function_pointer(T *p_instance,
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
const char *p_func_text,
|
||||
#endif
|
||||
R (T::*p_method)(P...)) {
|
||||
typedef CallableCustomMethodPointer<T, R, P...> CCMP; // Messes with memnew otherwise.
|
||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
|
||||
#endif
|
||||
return Callable(ccmp);
|
||||
}
|
||||
|
||||
// CONST VERSION
|
||||
|
||||
template <typename T, typename R, typename... P>
|
||||
class CallableCustomMethodPointerRetC : public CallableCustomMethodPointerBase {
|
||||
class CallableCustomMethodPointerC : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
T *instance;
|
||||
uint64_t object_id;
|
||||
|
@ -204,10 +173,14 @@ public:
|
|||
|
||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
|
||||
ERR_FAIL_NULL_MSG(ObjectDB::get_instance(ObjectID(data.object_id)), "Invalid Object id '" + uitos(data.object_id) + "', can't call method.");
|
||||
if constexpr (std::is_same<R, void>::value) {
|
||||
call_with_variant_argsc(data.instance, data.method, p_arguments, p_argcount, r_call_error);
|
||||
} else {
|
||||
call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||
}
|
||||
}
|
||||
|
||||
CallableCustomMethodPointerRetC(T *p_instance, R (T::*p_method)(P...) const) {
|
||||
CallableCustomMethodPointerC(T *p_instance, R (T::*p_method)(P...) const) {
|
||||
memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
|
||||
data.instance = p_instance;
|
||||
data.object_id = p_instance->get_instance_id();
|
||||
|
@ -216,13 +189,27 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... P>
|
||||
Callable create_custom_callable_function_pointer(T *p_instance,
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
const char *p_func_text,
|
||||
#endif
|
||||
void (T::*p_method)(P...) const) {
|
||||
typedef CallableCustomMethodPointerC<T, void, P...> CCMP; // Messes with memnew otherwise.
|
||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
|
||||
#endif
|
||||
return Callable(ccmp);
|
||||
}
|
||||
|
||||
template <typename T, typename R, typename... P>
|
||||
Callable create_custom_callable_function_pointer(T *p_instance,
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
const char *p_func_text,
|
||||
#endif
|
||||
R (T::*p_method)(P...) const) {
|
||||
typedef CallableCustomMethodPointerRetC<T, R, P...> CCMP; // Messes with memnew otherwise.
|
||||
typedef CallableCustomMethodPointerC<T, R, P...> CCMP; // Messes with memnew otherwise.
|
||||
CCMP *ccmp = memnew(CCMP(p_instance, p_method));
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
|
||||
|
@ -238,54 +225,8 @@ Callable create_custom_callable_function_pointer(T *p_instance,
|
|||
|
||||
// STATIC VERSIONS
|
||||
|
||||
template <typename... P>
|
||||
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
void (*method)(P...);
|
||||
} data;
|
||||
|
||||
public:
|
||||
virtual bool is_valid() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual ObjectID get_object() const override {
|
||||
return ObjectID();
|
||||
}
|
||||
|
||||
virtual int get_argument_count(bool &r_is_valid) const override {
|
||||
r_is_valid = true;
|
||||
return sizeof...(P);
|
||||
}
|
||||
|
||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
|
||||
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||
r_return_value = Variant();
|
||||
}
|
||||
|
||||
CallableCustomStaticMethodPointer(void (*p_method)(P...)) {
|
||||
memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
|
||||
data.method = p_method;
|
||||
_setup((uint32_t *)&data, sizeof(Data));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... P>
|
||||
Callable create_custom_callable_static_function_pointer(
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
const char *p_func_text,
|
||||
#endif
|
||||
void (*p_method)(P...)) {
|
||||
typedef CallableCustomStaticMethodPointer<P...> CCMP; // Messes with memnew otherwise.
|
||||
CCMP *ccmp = memnew(CCMP(p_method));
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
|
||||
#endif
|
||||
return Callable(ccmp);
|
||||
}
|
||||
|
||||
template <typename R, typename... P>
|
||||
class CallableCustomStaticMethodPointerRet : public CallableCustomMethodPointerBase {
|
||||
class CallableCustomStaticMethodPointer : public CallableCustomMethodPointerBase {
|
||||
struct Data {
|
||||
R(*method)
|
||||
(P...);
|
||||
|
@ -306,23 +247,41 @@ public:
|
|||
}
|
||||
|
||||
virtual void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override {
|
||||
if constexpr (std::is_same<R, void>::value) {
|
||||
call_with_variant_args_static(data.method, p_arguments, p_argcount, r_call_error);
|
||||
} else {
|
||||
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||
}
|
||||
}
|
||||
|
||||
CallableCustomStaticMethodPointerRet(R (*p_method)(P...)) {
|
||||
CallableCustomStaticMethodPointer(R (*p_method)(P...)) {
|
||||
memset(&data, 0, sizeof(Data)); // Clear beforehand, may have padding bytes.
|
||||
data.method = p_method;
|
||||
_setup((uint32_t *)&data, sizeof(Data));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... P>
|
||||
Callable create_custom_callable_static_function_pointer(
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
const char *p_func_text,
|
||||
#endif
|
||||
void (*p_method)(P...)) {
|
||||
typedef CallableCustomStaticMethodPointer<void, P...> CCMP; // Messes with memnew otherwise.
|
||||
CCMP *ccmp = memnew(CCMP(p_method));
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
|
||||
#endif
|
||||
return Callable(ccmp);
|
||||
}
|
||||
|
||||
template <typename R, typename... P>
|
||||
Callable create_custom_callable_static_function_pointer(
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
const char *p_func_text,
|
||||
#endif
|
||||
R (*p_method)(P...)) {
|
||||
typedef CallableCustomStaticMethodPointerRet<R, P...> CCMP; // Messes with memnew otherwise.
|
||||
typedef CallableCustomStaticMethodPointer<R, P...> CCMP; // Messes with memnew otherwise.
|
||||
CCMP *ccmp = memnew(CCMP(p_method));
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
ccmp->set_text(p_func_text + 1); // Try to get rid of the ampersand.
|
||||
|
|
|
@ -2,7 +2,6 @@ proto = """#define GDVIRTUAL$VER($RET m_name $ARG)\\
|
|||
StringName _gdvirtual_##m_name##_sn = #m_name;\\
|
||||
mutable bool _gdvirtual_##m_name##_initialized = false;\\
|
||||
mutable void *_gdvirtual_##m_name = nullptr;\\
|
||||
template <bool required>\\
|
||||
_FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST {\\
|
||||
ScriptInstance *_script_instance = ((Object *)(this))->get_script_instance();\\
|
||||
if (_script_instance) {\\
|
||||
|
@ -36,10 +35,8 @@ proto = """#define GDVIRTUAL$VER($RET m_name $ARG)\\
|
|||
}\\
|
||||
return true;\\
|
||||
}\\
|
||||
if (required) {\\
|
||||
ERR_PRINT_ONCE("Required virtual method " + get_class() + "::" + #m_name + " must be overridden before calling.");\\
|
||||
$REQCHECK\\
|
||||
$RVOID\\
|
||||
}\\
|
||||
return false;\\
|
||||
}\\
|
||||
_FORCE_INLINE_ bool _gdvirtual_##m_name##_overridden() const {\\
|
||||
|
@ -73,10 +70,11 @@ proto = """#define GDVIRTUAL$VER($RET m_name $ARG)\\
|
|||
"""
|
||||
|
||||
|
||||
def generate_version(argcount, const=False, returns=False):
|
||||
def generate_version(argcount, const=False, returns=False, required=False):
|
||||
s = proto
|
||||
sproto = str(argcount)
|
||||
method_info = ""
|
||||
method_flags = "METHOD_FLAG_VIRTUAL"
|
||||
if returns:
|
||||
sproto += "R"
|
||||
s = s.replace("$RET", "m_ret,")
|
||||
|
@ -86,17 +84,27 @@ def generate_version(argcount, const=False, returns=False):
|
|||
method_info += "\t\tmethod_info.return_val_metadata = GetTypeInfo<m_ret>::METADATA;"
|
||||
else:
|
||||
s = s.replace("$RET ", "")
|
||||
s = s.replace("\t\t\t$RVOID\\\n", "")
|
||||
s = s.replace("\t\t$RVOID\\\n", "")
|
||||
s = s.replace("\t\t\t$CALLPTRRETDEF\\\n", "")
|
||||
|
||||
if const:
|
||||
sproto += "C"
|
||||
method_flags += " | METHOD_FLAG_CONST"
|
||||
s = s.replace("$CONST", "const")
|
||||
s = s.replace("$METHOD_FLAGS", "METHOD_FLAG_VIRTUAL | METHOD_FLAG_CONST")
|
||||
else:
|
||||
s = s.replace("$CONST ", "")
|
||||
s = s.replace("$METHOD_FLAGS", "METHOD_FLAG_VIRTUAL")
|
||||
|
||||
if required:
|
||||
sproto += "_REQUIRED"
|
||||
method_flags += " | METHOD_FLAG_VIRTUAL_REQUIRED"
|
||||
s = s.replace(
|
||||
"$REQCHECK",
|
||||
'ERR_PRINT_ONCE("Required virtual method " + get_class() + "::" + #m_name + " must be overridden before calling.");',
|
||||
)
|
||||
else:
|
||||
s = s.replace("\t\t$REQCHECK\\\n", "")
|
||||
|
||||
s = s.replace("$METHOD_FLAGS", method_flags)
|
||||
s = s.replace("$VER", sproto)
|
||||
argtext = ""
|
||||
callargtext = ""
|
||||
|
@ -198,6 +206,10 @@ def run(target, source, env):
|
|||
txt += generate_version(i, False, True)
|
||||
txt += generate_version(i, True, False)
|
||||
txt += generate_version(i, True, True)
|
||||
txt += generate_version(i, False, False, True)
|
||||
txt += generate_version(i, False, True, True)
|
||||
txt += generate_version(i, True, False, True)
|
||||
txt += generate_version(i, True, True, True)
|
||||
|
||||
txt += "#endif // GDVIRTUAL_GEN_H\n"
|
||||
|
||||
|
|
|
@ -44,14 +44,17 @@
|
|||
#ifdef DEBUG_ENABLED
|
||||
|
||||
struct _ObjectDebugLock {
|
||||
Object *obj;
|
||||
ObjectID obj_id;
|
||||
|
||||
_ObjectDebugLock(Object *p_obj) {
|
||||
obj = p_obj;
|
||||
obj->_lock_index.ref();
|
||||
obj_id = p_obj->get_instance_id();
|
||||
p_obj->_lock_index.ref();
|
||||
}
|
||||
~_ObjectDebugLock() {
|
||||
obj->_lock_index.unref();
|
||||
Object *obj_ptr = ObjectDB::get_instance(obj_id);
|
||||
if (likely(obj_ptr)) {
|
||||
obj_ptr->_lock_index.unref();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1454,6 +1457,24 @@ bool Object::is_connected(const StringName &p_signal, const Callable &p_callable
|
|||
return s->slot_map.has(*p_callable.get_base_comparator());
|
||||
}
|
||||
|
||||
bool Object::has_connections(const StringName &p_signal) const {
|
||||
const SignalData *s = signal_map.getptr(p_signal);
|
||||
if (!s) {
|
||||
bool signal_is_valid = ClassDB::has_signal(get_class_name(), p_signal);
|
||||
if (signal_is_valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!script.is_null() && Ref<Script>(script)->has_script_signal(p_signal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ERR_FAIL_V_MSG(false, "Nonexistent signal: " + p_signal + ".");
|
||||
}
|
||||
|
||||
return !s->slot_map.is_empty();
|
||||
}
|
||||
|
||||
void Object::disconnect(const StringName &p_signal, const Callable &p_callable) {
|
||||
_disconnect(p_signal, p_callable);
|
||||
}
|
||||
|
@ -1524,21 +1545,21 @@ void Object::initialize_class() {
|
|||
initialized = true;
|
||||
}
|
||||
|
||||
StringName Object::get_translation_domain() const {
|
||||
return _translation_domain;
|
||||
}
|
||||
|
||||
void Object::set_translation_domain(const StringName &p_domain) {
|
||||
_translation_domain = p_domain;
|
||||
}
|
||||
|
||||
String Object::tr(const StringName &p_message, const StringName &p_context) const {
|
||||
if (!_can_translate || !TranslationServer::get_singleton()) {
|
||||
return p_message;
|
||||
}
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint() || Engine::get_singleton()->is_project_manager_hint()) {
|
||||
String tr_msg = TranslationServer::get_singleton()->extractable_translate(p_message, p_context);
|
||||
if (!tr_msg.is_empty() && tr_msg != p_message) {
|
||||
return tr_msg;
|
||||
}
|
||||
|
||||
return TranslationServer::get_singleton()->tool_translate(p_message, p_context);
|
||||
}
|
||||
|
||||
return TranslationServer::get_singleton()->translate(p_message, p_context);
|
||||
const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain(get_translation_domain());
|
||||
return domain->translate(p_message, p_context);
|
||||
}
|
||||
|
||||
String Object::tr_n(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
|
||||
|
@ -1550,16 +1571,8 @@ String Object::tr_n(const StringName &p_message, const StringName &p_message_plu
|
|||
return p_message_plural;
|
||||
}
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint() || Engine::get_singleton()->is_project_manager_hint()) {
|
||||
String tr_msg = TranslationServer::get_singleton()->extractable_translate_plural(p_message, p_message_plural, p_n, p_context);
|
||||
if (!tr_msg.is_empty() && tr_msg != p_message && tr_msg != p_message_plural) {
|
||||
return tr_msg;
|
||||
}
|
||||
|
||||
return TranslationServer::get_singleton()->tool_translate_plural(p_message, p_message_plural, p_n, p_context);
|
||||
}
|
||||
|
||||
return TranslationServer::get_singleton()->translate_plural(p_message, p_message_plural, p_n, p_context);
|
||||
const Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain(get_translation_domain());
|
||||
return domain->translate_plural(p_message, p_message_plural, p_n, p_context);
|
||||
}
|
||||
|
||||
void Object::_clear_internal_resource_paths(const Variant &p_var) {
|
||||
|
@ -1702,6 +1715,7 @@ void Object::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("connect", "signal", "callable", "flags"), &Object::connect, DEFVAL(0));
|
||||
ClassDB::bind_method(D_METHOD("disconnect", "signal", "callable"), &Object::disconnect);
|
||||
ClassDB::bind_method(D_METHOD("is_connected", "signal", "callable"), &Object::is_connected);
|
||||
ClassDB::bind_method(D_METHOD("has_connections", "signal"), &Object::has_connections);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_block_signals", "enable"), &Object::set_block_signals);
|
||||
ClassDB::bind_method(D_METHOD("is_blocking_signals"), &Object::is_blocking_signals);
|
||||
|
@ -1711,6 +1725,8 @@ void Object::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("can_translate_messages"), &Object::can_translate_messages);
|
||||
ClassDB::bind_method(D_METHOD("tr", "message", "context"), &Object::tr, DEFVAL(StringName()));
|
||||
ClassDB::bind_method(D_METHOD("tr_n", "message", "plural_message", "n", "context"), &Object::tr_n, DEFVAL(StringName()));
|
||||
ClassDB::bind_method(D_METHOD("get_translation_domain"), &Object::get_translation_domain);
|
||||
ClassDB::bind_method(D_METHOD("set_translation_domain", "domain"), &Object::set_translation_domain);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_queued_for_deletion"), &Object::is_queued_for_deletion);
|
||||
ClassDB::bind_method(D_METHOD("cancel_free"), &Object::cancel_free);
|
||||
|
|
|
@ -87,6 +87,7 @@ enum PropertyHint {
|
|||
PROPERTY_HINT_PASSWORD,
|
||||
PROPERTY_HINT_LAYERS_AVOIDANCE,
|
||||
PROPERTY_HINT_DICTIONARY_TYPE,
|
||||
PROPERTY_HINT_TOOL_BUTTON,
|
||||
PROPERTY_HINT_MAX,
|
||||
};
|
||||
|
||||
|
@ -215,6 +216,7 @@ enum MethodFlags {
|
|||
METHOD_FLAG_VARARG = 16,
|
||||
METHOD_FLAG_STATIC = 32,
|
||||
METHOD_FLAG_OBJECT_CORE = 64,
|
||||
METHOD_FLAG_VIRTUAL_REQUIRED = 128,
|
||||
METHOD_FLAGS_DEFAULT = METHOD_FLAG_NORMAL,
|
||||
};
|
||||
|
||||
|
@ -368,11 +370,8 @@ struct ObjectGDExtension {
|
|||
#endif
|
||||
};
|
||||
|
||||
#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call<false>(__VA_ARGS__)
|
||||
#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<false>(__VA_ARGS__)
|
||||
|
||||
#define GDVIRTUAL_REQUIRED_CALL(m_name, ...) _gdvirtual_##m_name##_call<true>(__VA_ARGS__)
|
||||
#define GDVIRTUAL_REQUIRED_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call<true>(__VA_ARGS__)
|
||||
#define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call(__VA_ARGS__)
|
||||
#define GDVIRTUAL_CALL_PTR(m_obj, m_name, ...) m_obj->_gdvirtual_##m_name##_call(__VA_ARGS__)
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
#define GDVIRTUAL_BIND(m_name, ...) ::ClassDB::add_virtual_method(get_class_static(), _gdvirtual_##m_name##_get_method_info(), true, sarray(__VA_ARGS__));
|
||||
|
@ -665,6 +664,8 @@ private:
|
|||
Object(bool p_reference);
|
||||
|
||||
protected:
|
||||
StringName _translation_domain;
|
||||
|
||||
_FORCE_INLINE_ bool _instance_binding_reference(bool p_reference) {
|
||||
bool can_die = true;
|
||||
if (_instance_bindings) {
|
||||
|
@ -930,6 +931,7 @@ public:
|
|||
MTVIRTUAL Error connect(const StringName &p_signal, const Callable &p_callable, uint32_t p_flags = 0);
|
||||
MTVIRTUAL void disconnect(const StringName &p_signal, const Callable &p_callable);
|
||||
MTVIRTUAL bool is_connected(const StringName &p_signal, const Callable &p_callable) const;
|
||||
MTVIRTUAL bool has_connections(const StringName &p_signal) const;
|
||||
|
||||
template <typename... VarArgs>
|
||||
void call_deferred(const StringName &p_name, VarArgs... p_args) {
|
||||
|
@ -954,6 +956,9 @@ public:
|
|||
_FORCE_INLINE_ void set_message_translation(bool p_enable) { _can_translate = p_enable; }
|
||||
_FORCE_INLINE_ bool can_translate_messages() const { return _can_translate; }
|
||||
|
||||
virtual StringName get_translation_domain() const;
|
||||
virtual void set_translation_domain(const StringName &p_domain);
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
|
||||
void editor_set_section_unfold(const String &p_section, bool p_unfolded);
|
||||
|
|
|
@ -174,6 +174,8 @@ void Script::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("is_tool"), &Script::is_tool);
|
||||
ClassDB::bind_method(D_METHOD("is_abstract"), &Script::is_abstract);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_rpc_config"), &Script::get_rpc_config);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "source_code", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_source_code", "get_source_code");
|
||||
}
|
||||
|
||||
|
@ -189,7 +191,17 @@ void Script::reload_from_file() {
|
|||
set_source_code(rel->get_source_code());
|
||||
set_last_modified_time(rel->get_last_modified_time());
|
||||
|
||||
reload();
|
||||
// Only reload the script when there are no compilation errors to prevent printing the error messages twice.
|
||||
if (rel->is_valid()) {
|
||||
if (Engine::get_singleton()->is_editor_hint() && is_tool()) {
|
||||
get_language()->reload_tool_script(this, true);
|
||||
} else {
|
||||
// It's important to set p_keep_state to true in order to manage reloading scripts
|
||||
// that are currently instantiated.
|
||||
reload(true);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
Resource::reload_from_file();
|
||||
#endif
|
||||
|
|
|
@ -112,7 +112,10 @@ class Script : public Resource {
|
|||
OBJ_SAVE_TYPE(Script);
|
||||
|
||||
protected:
|
||||
virtual bool editor_can_reload_from_file() override { return false; } // this is handled by editor better
|
||||
// Scripts are reloaded via the Script Editor when edited in Godot,
|
||||
// the LSP server when edited in a connected external editor, or
|
||||
// through EditorFileSystem::_update_script_documentation when updated directly on disk.
|
||||
virtual bool editor_can_reload_from_file() override { return false; }
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
|
@ -182,7 +185,7 @@ public:
|
|||
|
||||
virtual bool is_placeholder_fallback_enabled() const { return false; }
|
||||
|
||||
virtual const Variant get_rpc_config() const = 0;
|
||||
virtual Variant get_rpc_config() const = 0;
|
||||
|
||||
Script() {}
|
||||
};
|
||||
|
|
|
@ -57,16 +57,16 @@ public:
|
|||
EXBIND1RC(bool, inherits_script, const Ref<Script> &)
|
||||
EXBIND0RC(StringName, get_instance_base_type)
|
||||
|
||||
GDVIRTUAL1RC(GDExtensionPtr<void>, _instance_create, Object *)
|
||||
GDVIRTUAL1RC_REQUIRED(GDExtensionPtr<void>, _instance_create, Object *)
|
||||
virtual ScriptInstance *instance_create(Object *p_this) override {
|
||||
GDExtensionPtr<void> ret = nullptr;
|
||||
GDVIRTUAL_REQUIRED_CALL(_instance_create, p_this, ret);
|
||||
GDVIRTUAL_CALL(_instance_create, p_this, ret);
|
||||
return reinterpret_cast<ScriptInstance *>(ret.operator void *());
|
||||
}
|
||||
GDVIRTUAL1RC(GDExtensionPtr<void>, _placeholder_instance_create, Object *)
|
||||
GDVIRTUAL1RC_REQUIRED(GDExtensionPtr<void>, _placeholder_instance_create, Object *)
|
||||
PlaceHolderScriptInstance *placeholder_instance_create(Object *p_this) override {
|
||||
GDExtensionPtr<void> ret = nullptr;
|
||||
GDVIRTUAL_REQUIRED_CALL(_placeholder_instance_create, p_this, ret);
|
||||
GDVIRTUAL_CALL(_placeholder_instance_create, p_this, ret);
|
||||
return reinterpret_cast<PlaceHolderScriptInstance *>(ret.operator void *());
|
||||
}
|
||||
|
||||
|
@ -76,12 +76,12 @@ public:
|
|||
EXBIND1(set_source_code, const String &)
|
||||
EXBIND1R(Error, reload, bool)
|
||||
|
||||
GDVIRTUAL0RC(TypedArray<Dictionary>, _get_documentation)
|
||||
GDVIRTUAL0RC_REQUIRED(TypedArray<Dictionary>, _get_documentation)
|
||||
GDVIRTUAL0RC(String, _get_class_icon_path)
|
||||
#ifdef TOOLS_ENABLED
|
||||
virtual Vector<DocData::ClassDoc> get_documentation() const override {
|
||||
TypedArray<Dictionary> doc;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_documentation, doc);
|
||||
GDVIRTUAL_CALL(_get_documentation, doc);
|
||||
|
||||
Vector<DocData::ClassDoc> class_doc;
|
||||
for (int i = 0; i < doc.size(); i++) {
|
||||
|
@ -114,10 +114,10 @@ public:
|
|||
return Script::get_script_method_argument_count(p_method, r_is_valid);
|
||||
}
|
||||
|
||||
GDVIRTUAL1RC(Dictionary, _get_method_info, const StringName &)
|
||||
GDVIRTUAL1RC_REQUIRED(Dictionary, _get_method_info, const StringName &)
|
||||
virtual MethodInfo get_method_info(const StringName &p_method) const override {
|
||||
Dictionary mi;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_method_info, p_method, mi);
|
||||
GDVIRTUAL_CALL(_get_method_info, p_method, mi);
|
||||
return MethodInfo::from_dict(mi);
|
||||
}
|
||||
|
||||
|
@ -133,47 +133,47 @@ public:
|
|||
EXBIND0RC(ScriptLanguage *, get_language)
|
||||
EXBIND1RC(bool, has_script_signal, const StringName &)
|
||||
|
||||
GDVIRTUAL0RC(TypedArray<Dictionary>, _get_script_signal_list)
|
||||
GDVIRTUAL0RC_REQUIRED(TypedArray<Dictionary>, _get_script_signal_list)
|
||||
|
||||
virtual void get_script_signal_list(List<MethodInfo> *r_signals) const override {
|
||||
TypedArray<Dictionary> sl;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_script_signal_list, sl);
|
||||
GDVIRTUAL_CALL(_get_script_signal_list, sl);
|
||||
for (int i = 0; i < sl.size(); i++) {
|
||||
r_signals->push_back(MethodInfo::from_dict(sl[i]));
|
||||
}
|
||||
}
|
||||
|
||||
GDVIRTUAL1RC(bool, _has_property_default_value, const StringName &)
|
||||
GDVIRTUAL1RC(Variant, _get_property_default_value, const StringName &)
|
||||
GDVIRTUAL1RC_REQUIRED(bool, _has_property_default_value, const StringName &)
|
||||
GDVIRTUAL1RC_REQUIRED(Variant, _get_property_default_value, const StringName &)
|
||||
|
||||
virtual bool get_property_default_value(const StringName &p_property, Variant &r_value) const override {
|
||||
bool has_dv = false;
|
||||
if (!GDVIRTUAL_REQUIRED_CALL(_has_property_default_value, p_property, has_dv) || !has_dv) {
|
||||
if (!GDVIRTUAL_CALL(_has_property_default_value, p_property, has_dv) || !has_dv) {
|
||||
return false;
|
||||
}
|
||||
Variant ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_property_default_value, p_property, ret);
|
||||
GDVIRTUAL_CALL(_get_property_default_value, p_property, ret);
|
||||
r_value = ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
EXBIND0(update_exports)
|
||||
|
||||
GDVIRTUAL0RC(TypedArray<Dictionary>, _get_script_method_list)
|
||||
GDVIRTUAL0RC_REQUIRED(TypedArray<Dictionary>, _get_script_method_list)
|
||||
|
||||
virtual void get_script_method_list(List<MethodInfo> *r_methods) const override {
|
||||
TypedArray<Dictionary> sl;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_script_method_list, sl);
|
||||
GDVIRTUAL_CALL(_get_script_method_list, sl);
|
||||
for (int i = 0; i < sl.size(); i++) {
|
||||
r_methods->push_back(MethodInfo::from_dict(sl[i]));
|
||||
}
|
||||
}
|
||||
|
||||
GDVIRTUAL0RC(TypedArray<Dictionary>, _get_script_property_list)
|
||||
GDVIRTUAL0RC_REQUIRED(TypedArray<Dictionary>, _get_script_property_list)
|
||||
|
||||
virtual void get_script_property_list(List<PropertyInfo> *r_propertys) const override {
|
||||
TypedArray<Dictionary> sl;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_script_property_list, sl);
|
||||
GDVIRTUAL_CALL(_get_script_property_list, sl);
|
||||
for (int i = 0; i < sl.size(); i++) {
|
||||
r_propertys->push_back(PropertyInfo::from_dict(sl[i]));
|
||||
}
|
||||
|
@ -181,21 +181,21 @@ public:
|
|||
|
||||
EXBIND1RC(int, get_member_line, const StringName &)
|
||||
|
||||
GDVIRTUAL0RC(Dictionary, _get_constants)
|
||||
GDVIRTUAL0RC_REQUIRED(Dictionary, _get_constants)
|
||||
|
||||
virtual void get_constants(HashMap<StringName, Variant> *p_constants) override {
|
||||
Dictionary constants;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_constants, constants);
|
||||
GDVIRTUAL_CALL(_get_constants, constants);
|
||||
List<Variant> keys;
|
||||
constants.get_key_list(&keys);
|
||||
for (const Variant &K : keys) {
|
||||
p_constants->insert(K, constants[K]);
|
||||
}
|
||||
}
|
||||
GDVIRTUAL0RC(TypedArray<StringName>, _get_members)
|
||||
GDVIRTUAL0RC_REQUIRED(TypedArray<StringName>, _get_members)
|
||||
virtual void get_members(HashSet<StringName> *p_members) override {
|
||||
TypedArray<StringName> members;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_members, members);
|
||||
GDVIRTUAL_CALL(_get_members, members);
|
||||
for (int i = 0; i < members.size(); i++) {
|
||||
p_members->insert(members[i]);
|
||||
}
|
||||
|
@ -203,11 +203,11 @@ public:
|
|||
|
||||
EXBIND0RC(bool, is_placeholder_fallback_enabled)
|
||||
|
||||
GDVIRTUAL0RC(Variant, _get_rpc_config)
|
||||
GDVIRTUAL0RC_REQUIRED(Variant, _get_rpc_config)
|
||||
|
||||
virtual const Variant get_rpc_config() const override {
|
||||
virtual Variant get_rpc_config() const override {
|
||||
Variant ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_rpc_config, ret);
|
||||
GDVIRTUAL_CALL(_get_rpc_config, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -233,22 +233,22 @@ public:
|
|||
|
||||
/* EDITOR FUNCTIONS */
|
||||
|
||||
GDVIRTUAL0RC(Vector<String>, _get_reserved_words)
|
||||
GDVIRTUAL0RC_REQUIRED(Vector<String>, _get_reserved_words)
|
||||
|
||||
virtual void get_reserved_words(List<String> *p_words) const override {
|
||||
Vector<String> ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_reserved_words, ret);
|
||||
GDVIRTUAL_CALL(_get_reserved_words, ret);
|
||||
for (int i = 0; i < ret.size(); i++) {
|
||||
p_words->push_back(ret[i]);
|
||||
}
|
||||
}
|
||||
EXBIND1RC(bool, is_control_flow_keyword, const String &)
|
||||
|
||||
GDVIRTUAL0RC(Vector<String>, _get_comment_delimiters)
|
||||
GDVIRTUAL0RC_REQUIRED(Vector<String>, _get_comment_delimiters)
|
||||
|
||||
virtual void get_comment_delimiters(List<String> *p_words) const override {
|
||||
Vector<String> ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_comment_delimiters, ret);
|
||||
GDVIRTUAL_CALL(_get_comment_delimiters, ret);
|
||||
for (int i = 0; i < ret.size(); i++) {
|
||||
p_words->push_back(ret[i]);
|
||||
}
|
||||
|
@ -264,11 +264,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
GDVIRTUAL0RC(Vector<String>, _get_string_delimiters)
|
||||
GDVIRTUAL0RC_REQUIRED(Vector<String>, _get_string_delimiters)
|
||||
|
||||
virtual void get_string_delimiters(List<String> *p_words) const override {
|
||||
Vector<String> ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_string_delimiters, ret);
|
||||
GDVIRTUAL_CALL(_get_string_delimiters, ret);
|
||||
for (int i = 0; i < ret.size(); i++) {
|
||||
p_words->push_back(ret[i]);
|
||||
}
|
||||
|
@ -276,11 +276,11 @@ public:
|
|||
|
||||
EXBIND3RC(Ref<Script>, make_template, const String &, const String &, const String &)
|
||||
|
||||
GDVIRTUAL1RC(TypedArray<Dictionary>, _get_built_in_templates, StringName)
|
||||
GDVIRTUAL1RC_REQUIRED(TypedArray<Dictionary>, _get_built_in_templates, StringName)
|
||||
|
||||
virtual Vector<ScriptTemplate> get_built_in_templates(const StringName &p_object) override {
|
||||
TypedArray<Dictionary> ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_built_in_templates, p_object, ret);
|
||||
GDVIRTUAL_CALL(_get_built_in_templates, p_object, ret);
|
||||
Vector<ScriptTemplate> stret;
|
||||
for (int i = 0; i < ret.size(); i++) {
|
||||
Dictionary d = ret[i];
|
||||
|
@ -304,10 +304,10 @@ public:
|
|||
|
||||
EXBIND0R(bool, is_using_templates)
|
||||
|
||||
GDVIRTUAL6RC(Dictionary, _validate, const String &, const String &, bool, bool, bool, bool)
|
||||
GDVIRTUAL6RC_REQUIRED(Dictionary, _validate, const String &, const String &, bool, bool, bool, bool)
|
||||
virtual bool validate(const String &p_script, const String &p_path = "", List<String> *r_functions = nullptr, List<ScriptError> *r_errors = nullptr, List<Warning> *r_warnings = nullptr, HashSet<int> *r_safe_lines = nullptr) const override {
|
||||
Dictionary ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_validate, p_script, p_path, r_functions != nullptr, r_errors != nullptr, r_warnings != nullptr, r_safe_lines != nullptr, ret);
|
||||
GDVIRTUAL_CALL(_validate, p_script, p_path, r_functions != nullptr, r_errors != nullptr, r_warnings != nullptr, r_safe_lines != nullptr, ret);
|
||||
if (!ret.has("valid")) {
|
||||
return false;
|
||||
}
|
||||
|
@ -371,10 +371,10 @@ public:
|
|||
}
|
||||
|
||||
EXBIND1RC(String, validate_path, const String &)
|
||||
GDVIRTUAL0RC(Object *, _create_script)
|
||||
GDVIRTUAL0RC_REQUIRED(Object *, _create_script)
|
||||
Script *create_script() const override {
|
||||
Object *ret = nullptr;
|
||||
GDVIRTUAL_REQUIRED_CALL(_create_script, ret);
|
||||
GDVIRTUAL_CALL(_create_script, ret);
|
||||
return Object::cast_to<Script>(ret);
|
||||
}
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
|
@ -400,11 +400,11 @@ public:
|
|||
return ScriptNameCasing::SCRIPT_NAME_CASING_SNAKE_CASE;
|
||||
}
|
||||
|
||||
GDVIRTUAL3RC(Dictionary, _complete_code, const String &, const String &, Object *)
|
||||
GDVIRTUAL3RC_REQUIRED(Dictionary, _complete_code, const String &, const String &, Object *)
|
||||
|
||||
virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<CodeCompletionOption> *r_options, bool &r_force, String &r_call_hint) override {
|
||||
Dictionary ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_complete_code, p_code, p_path, p_owner, ret);
|
||||
GDVIRTUAL_CALL(_complete_code, p_code, p_path, p_owner, ret);
|
||||
if (!ret.has("result")) {
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
|
@ -449,11 +449,11 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
GDVIRTUAL4RC(Dictionary, _lookup_code, const String &, const String &, const String &, Object *)
|
||||
GDVIRTUAL4RC_REQUIRED(Dictionary, _lookup_code, const String &, const String &, const String &, Object *)
|
||||
|
||||
virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result) override {
|
||||
Dictionary ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_lookup_code, p_code, p_symbol, p_path, p_owner, ret);
|
||||
GDVIRTUAL_CALL(_lookup_code, p_code, p_symbol, p_path, p_owner, ret);
|
||||
if (!ret.has("result")) {
|
||||
return ERR_UNAVAILABLE;
|
||||
}
|
||||
|
@ -474,10 +474,10 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
GDVIRTUAL3RC(String, _auto_indent_code, const String &, int, int)
|
||||
GDVIRTUAL3RC_REQUIRED(String, _auto_indent_code, const String &, int, int)
|
||||
virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const override {
|
||||
String ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_auto_indent_code, p_code, p_from_line, p_to_line, ret);
|
||||
GDVIRTUAL_CALL(_auto_indent_code, p_code, p_from_line, p_to_line, ret);
|
||||
p_code = ret;
|
||||
}
|
||||
EXBIND2(add_global_constant, const StringName &, const Variant &)
|
||||
|
@ -496,10 +496,10 @@ public:
|
|||
EXBIND1RC(String, debug_get_stack_level_function, int)
|
||||
EXBIND1RC(String, debug_get_stack_level_source, int)
|
||||
|
||||
GDVIRTUAL3R(Dictionary, _debug_get_stack_level_locals, int, int, int)
|
||||
GDVIRTUAL3R_REQUIRED(Dictionary, _debug_get_stack_level_locals, int, int, int)
|
||||
virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) override {
|
||||
Dictionary ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_debug_get_stack_level_locals, p_level, p_max_subitems, p_max_depth, ret);
|
||||
GDVIRTUAL_CALL(_debug_get_stack_level_locals, p_level, p_max_subitems, p_max_depth, ret);
|
||||
if (ret.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -516,10 +516,10 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
GDVIRTUAL3R(Dictionary, _debug_get_stack_level_members, int, int, int)
|
||||
GDVIRTUAL3R_REQUIRED(Dictionary, _debug_get_stack_level_members, int, int, int)
|
||||
virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) override {
|
||||
Dictionary ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_debug_get_stack_level_members, p_level, p_max_subitems, p_max_depth, ret);
|
||||
GDVIRTUAL_CALL(_debug_get_stack_level_members, p_level, p_max_subitems, p_max_depth, ret);
|
||||
if (ret.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -536,17 +536,17 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
GDVIRTUAL1R(GDExtensionPtr<void>, _debug_get_stack_level_instance, int)
|
||||
GDVIRTUAL1R_REQUIRED(GDExtensionPtr<void>, _debug_get_stack_level_instance, int)
|
||||
|
||||
virtual ScriptInstance *debug_get_stack_level_instance(int p_level) override {
|
||||
GDExtensionPtr<void> ret = nullptr;
|
||||
GDVIRTUAL_REQUIRED_CALL(_debug_get_stack_level_instance, p_level, ret);
|
||||
GDVIRTUAL_CALL(_debug_get_stack_level_instance, p_level, ret);
|
||||
return reinterpret_cast<ScriptInstance *>(ret.operator void *());
|
||||
}
|
||||
GDVIRTUAL2R(Dictionary, _debug_get_globals, int, int)
|
||||
GDVIRTUAL2R_REQUIRED(Dictionary, _debug_get_globals, int, int)
|
||||
virtual void debug_get_globals(List<String> *p_globals, List<Variant> *p_values, int p_max_subitems = -1, int p_max_depth = -1) override {
|
||||
Dictionary ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_debug_get_globals, p_max_subitems, p_max_depth, ret);
|
||||
GDVIRTUAL_CALL(_debug_get_globals, p_max_subitems, p_max_depth, ret);
|
||||
if (ret.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -566,10 +566,10 @@ public:
|
|||
|
||||
EXBIND4R(String, debug_parse_stack_level_expression, int, const String &, int, int)
|
||||
|
||||
GDVIRTUAL0R(TypedArray<Dictionary>, _debug_get_current_stack_info)
|
||||
GDVIRTUAL0R_REQUIRED(TypedArray<Dictionary>, _debug_get_current_stack_info)
|
||||
virtual Vector<StackInfo> debug_get_current_stack_info() override {
|
||||
TypedArray<Dictionary> ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_debug_get_current_stack_info, ret);
|
||||
GDVIRTUAL_CALL(_debug_get_current_stack_info, ret);
|
||||
Vector<StackInfo> sret;
|
||||
for (const Variant &var : ret) {
|
||||
StackInfo si;
|
||||
|
@ -590,29 +590,29 @@ public:
|
|||
EXBIND2(reload_tool_script, const Ref<Script> &, bool)
|
||||
/* LOADER FUNCTIONS */
|
||||
|
||||
GDVIRTUAL0RC(PackedStringArray, _get_recognized_extensions)
|
||||
GDVIRTUAL0RC_REQUIRED(PackedStringArray, _get_recognized_extensions)
|
||||
|
||||
virtual void get_recognized_extensions(List<String> *p_extensions) const override {
|
||||
PackedStringArray ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_recognized_extensions, ret);
|
||||
GDVIRTUAL_CALL(_get_recognized_extensions, ret);
|
||||
for (int i = 0; i < ret.size(); i++) {
|
||||
p_extensions->push_back(ret[i]);
|
||||
}
|
||||
}
|
||||
|
||||
GDVIRTUAL0RC(TypedArray<Dictionary>, _get_public_functions)
|
||||
GDVIRTUAL0RC_REQUIRED(TypedArray<Dictionary>, _get_public_functions)
|
||||
virtual void get_public_functions(List<MethodInfo> *p_functions) const override {
|
||||
TypedArray<Dictionary> ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_public_functions, ret);
|
||||
GDVIRTUAL_CALL(_get_public_functions, ret);
|
||||
for (const Variant &var : ret) {
|
||||
MethodInfo mi = MethodInfo::from_dict(var);
|
||||
p_functions->push_back(mi);
|
||||
}
|
||||
}
|
||||
GDVIRTUAL0RC(Dictionary, _get_public_constants)
|
||||
GDVIRTUAL0RC_REQUIRED(Dictionary, _get_public_constants)
|
||||
virtual void get_public_constants(List<Pair<String, Variant>> *p_constants) const override {
|
||||
Dictionary ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_public_constants, ret);
|
||||
GDVIRTUAL_CALL(_get_public_constants, ret);
|
||||
for (int i = 0; i < ret.size(); i++) {
|
||||
Dictionary d = ret[i];
|
||||
ERR_CONTINUE(!d.has("name"));
|
||||
|
@ -620,10 +620,10 @@ public:
|
|||
p_constants->push_back(Pair<String, Variant>(d["name"], d["value"]));
|
||||
}
|
||||
}
|
||||
GDVIRTUAL0RC(TypedArray<Dictionary>, _get_public_annotations)
|
||||
GDVIRTUAL0RC_REQUIRED(TypedArray<Dictionary>, _get_public_annotations)
|
||||
virtual void get_public_annotations(List<MethodInfo> *p_annotations) const override {
|
||||
TypedArray<Dictionary> ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_public_annotations, ret);
|
||||
GDVIRTUAL_CALL(_get_public_annotations, ret);
|
||||
for (const Variant &var : ret) {
|
||||
MethodInfo mi = MethodInfo::from_dict(var);
|
||||
p_annotations->push_back(mi);
|
||||
|
@ -634,19 +634,19 @@ public:
|
|||
EXBIND0(profiling_stop)
|
||||
EXBIND1(profiling_set_save_native_calls, bool)
|
||||
|
||||
GDVIRTUAL2R(int, _profiling_get_accumulated_data, GDExtensionPtr<ScriptLanguageExtensionProfilingInfo>, int)
|
||||
GDVIRTUAL2R_REQUIRED(int, _profiling_get_accumulated_data, GDExtensionPtr<ScriptLanguageExtensionProfilingInfo>, int)
|
||||
|
||||
virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) override {
|
||||
int ret = 0;
|
||||
GDVIRTUAL_REQUIRED_CALL(_profiling_get_accumulated_data, p_info_arr, p_info_max, ret);
|
||||
GDVIRTUAL_CALL(_profiling_get_accumulated_data, p_info_arr, p_info_max, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GDVIRTUAL2R(int, _profiling_get_frame_data, GDExtensionPtr<ScriptLanguageExtensionProfilingInfo>, int)
|
||||
GDVIRTUAL2R_REQUIRED(int, _profiling_get_frame_data, GDExtensionPtr<ScriptLanguageExtensionProfilingInfo>, int)
|
||||
|
||||
virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) override {
|
||||
int ret = 0;
|
||||
GDVIRTUAL_REQUIRED_CALL(_profiling_get_frame_data, p_info_arr, p_info_max, ret);
|
||||
GDVIRTUAL_CALL(_profiling_get_frame_data, p_info_arr, p_info_max, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -654,11 +654,11 @@ public:
|
|||
|
||||
EXBIND1RC(bool, handles_global_class_type, const String &)
|
||||
|
||||
GDVIRTUAL1RC(Dictionary, _get_global_class_name, const String &)
|
||||
GDVIRTUAL1RC_REQUIRED(Dictionary, _get_global_class_name, const String &)
|
||||
|
||||
virtual String get_global_class_name(const String &p_path, String *r_base_type = nullptr, String *r_icon_path = nullptr) const override {
|
||||
Dictionary ret;
|
||||
GDVIRTUAL_REQUIRED_CALL(_get_global_class_name, p_path, ret);
|
||||
GDVIRTUAL_CALL(_get_global_class_name, p_path, ret);
|
||||
if (!ret.has("name")) {
|
||||
return String();
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ void UndoRedo::Operation::delete_reference() {
|
|||
}
|
||||
}
|
||||
|
||||
void UndoRedo::_discard_redo() {
|
||||
void UndoRedo::discard_redo() {
|
||||
if (current_action == actions.size() - 1) {
|
||||
return;
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode, bool p_back
|
|||
uint64_t ticks = OS::get_singleton()->get_ticks_msec();
|
||||
|
||||
if (action_level == 0) {
|
||||
_discard_redo();
|
||||
discard_redo();
|
||||
|
||||
// Check if the merge operation is valid
|
||||
if (p_mode != MERGE_DISABLE && actions.size() && actions[actions.size() - 1].name == p_name && actions[actions.size() - 1].backward_undo_ops == p_backward_undo_ops && actions[actions.size() - 1].last_tick + 800 > ticks) {
|
||||
|
@ -288,7 +288,7 @@ void UndoRedo::end_force_keep_in_merge_ends() {
|
|||
}
|
||||
|
||||
void UndoRedo::_pop_history_tail() {
|
||||
_discard_redo();
|
||||
discard_redo();
|
||||
|
||||
if (!actions.size()) {
|
||||
return;
|
||||
|
@ -455,7 +455,7 @@ String UndoRedo::get_action_name(int p_id) {
|
|||
|
||||
void UndoRedo::clear_history(bool p_increase_version) {
|
||||
ERR_FAIL_COND(action_level > 0);
|
||||
_discard_redo();
|
||||
discard_redo();
|
||||
|
||||
while (actions.size()) {
|
||||
_pop_history_tail();
|
||||
|
|
|
@ -129,6 +129,7 @@ public:
|
|||
int get_current_action();
|
||||
String get_action_name(int p_id);
|
||||
void clear_history(bool p_increase_version = true);
|
||||
void discard_redo();
|
||||
|
||||
bool has_undo() const;
|
||||
bool has_redo() const;
|
||||
|
|
|
@ -180,13 +180,17 @@ void WorkerThreadPool::_process_task(Task *p_task) {
|
|||
|
||||
void WorkerThreadPool::_thread_function(void *p_user) {
|
||||
ThreadData *thread_data = (ThreadData *)p_user;
|
||||
|
||||
while (true) {
|
||||
Task *task_to_process = nullptr;
|
||||
{
|
||||
MutexLock lock(singleton->task_mutex);
|
||||
if (singleton->exit_threads) {
|
||||
return;
|
||||
|
||||
bool exit = singleton->_handle_runlevel(thread_data, lock);
|
||||
if (unlikely(exit)) {
|
||||
break;
|
||||
}
|
||||
|
||||
thread_data->signaled = false;
|
||||
|
||||
if (singleton->task_queue.first()) {
|
||||
|
@ -194,7 +198,6 @@ void WorkerThreadPool::_thread_function(void *p_user) {
|
|||
singleton->task_queue.remove(singleton->task_queue.first());
|
||||
} else {
|
||||
thread_data->cond_var.wait(lock);
|
||||
DEV_ASSERT(singleton->exit_threads || thread_data->signaled);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,19 +207,24 @@ void WorkerThreadPool::_thread_function(void *p_user) {
|
|||
}
|
||||
}
|
||||
|
||||
void WorkerThreadPool::_post_tasks_and_unlock(Task **p_tasks, uint32_t p_count, bool p_high_priority) {
|
||||
void WorkerThreadPool::_post_tasks(Task **p_tasks, uint32_t p_count, bool p_high_priority, MutexLock<BinaryMutex> &p_lock) {
|
||||
// Fall back to processing on the calling thread if there are no worker threads.
|
||||
// Separated into its own variable to make it easier to extend this logic
|
||||
// in custom builds.
|
||||
bool process_on_calling_thread = threads.size() == 0;
|
||||
if (process_on_calling_thread) {
|
||||
task_mutex.unlock();
|
||||
p_lock.temp_unlock();
|
||||
for (uint32_t i = 0; i < p_count; i++) {
|
||||
_process_task(p_tasks[i]);
|
||||
}
|
||||
p_lock.temp_relock();
|
||||
return;
|
||||
}
|
||||
|
||||
while (runlevel == RUNLEVEL_EXIT_LANGUAGES) {
|
||||
control_cond_var.wait(p_lock);
|
||||
}
|
||||
|
||||
uint32_t to_process = 0;
|
||||
uint32_t to_promote = 0;
|
||||
|
||||
|
@ -238,8 +246,6 @@ void WorkerThreadPool::_post_tasks_and_unlock(Task **p_tasks, uint32_t p_count,
|
|||
}
|
||||
|
||||
_notify_threads(caller_pool_thread, to_process, to_promote);
|
||||
|
||||
task_mutex.unlock();
|
||||
}
|
||||
|
||||
void WorkerThreadPool::_notify_threads(const ThreadData *p_current_thread_data, uint32_t p_process_count, uint32_t p_promote_count) {
|
||||
|
@ -323,9 +329,8 @@ WorkerThreadPool::TaskID WorkerThreadPool::add_native_task(void (*p_func)(void *
|
|||
}
|
||||
|
||||
WorkerThreadPool::TaskID WorkerThreadPool::_add_task(const Callable &p_callable, void (*p_func)(void *), void *p_userdata, BaseTemplateUserdata *p_template_userdata, bool p_high_priority, const String &p_description) {
|
||||
ERR_FAIL_COND_V_MSG(threads.is_empty(), INVALID_TASK_ID, "Can't add a task because the WorkerThreadPool is either not initialized yet or already terminated.");
|
||||
MutexLock<BinaryMutex> lock(task_mutex);
|
||||
|
||||
task_mutex.lock();
|
||||
// Get a free task
|
||||
Task *task = task_allocator.alloc();
|
||||
TaskID id = last_task++;
|
||||
|
@ -337,7 +342,7 @@ WorkerThreadPool::TaskID WorkerThreadPool::_add_task(const Callable &p_callable,
|
|||
task->template_userdata = p_template_userdata;
|
||||
tasks.insert(id, task);
|
||||
|
||||
_post_tasks_and_unlock(&task, 1, p_high_priority);
|
||||
_post_tasks(&task, 1, p_high_priority, lock);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
@ -444,22 +449,34 @@ void WorkerThreadPool::_unlock_unlockable_mutexes() {
|
|||
void WorkerThreadPool::_wait_collaboratively(ThreadData *p_caller_pool_thread, Task *p_task) {
|
||||
// Keep processing tasks until the condition to stop waiting is met.
|
||||
|
||||
#define IS_WAIT_OVER (unlikely(p_task == ThreadData::YIELDING) ? p_caller_pool_thread->yield_is_over : p_task->completed)
|
||||
|
||||
while (true) {
|
||||
Task *task_to_process = nullptr;
|
||||
bool relock_unlockables = false;
|
||||
{
|
||||
MutexLock lock(task_mutex);
|
||||
|
||||
bool was_signaled = p_caller_pool_thread->signaled;
|
||||
p_caller_pool_thread->signaled = false;
|
||||
|
||||
if (IS_WAIT_OVER) {
|
||||
if (unlikely(p_task == ThreadData::YIELDING)) {
|
||||
p_caller_pool_thread->yield_is_over = false;
|
||||
bool exit = _handle_runlevel(p_caller_pool_thread, lock);
|
||||
if (unlikely(exit)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!exit_threads && was_signaled) {
|
||||
bool wait_is_over = false;
|
||||
if (unlikely(p_task == ThreadData::YIELDING)) {
|
||||
if (p_caller_pool_thread->yield_is_over) {
|
||||
p_caller_pool_thread->yield_is_over = false;
|
||||
wait_is_over = true;
|
||||
}
|
||||
} else {
|
||||
if (p_task->completed) {
|
||||
wait_is_over = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (wait_is_over) {
|
||||
if (was_signaled) {
|
||||
// This thread was awaken for some additional reason, but it's about to exit.
|
||||
// Let's find out what may be pending and forward the requests.
|
||||
uint32_t to_process = task_queue.first() ? 1 : 0;
|
||||
|
@ -474,7 +491,6 @@ void WorkerThreadPool::_wait_collaboratively(ThreadData *p_caller_pool_thread, T
|
|||
break;
|
||||
}
|
||||
|
||||
if (!exit_threads) {
|
||||
if (p_caller_pool_thread->current_task->low_priority && low_priority_task_queue.first()) {
|
||||
if (_try_promote_low_priority_task()) {
|
||||
_notify_threads(p_caller_pool_thread, 1, 0);
|
||||
|
@ -491,13 +507,12 @@ void WorkerThreadPool::_wait_collaboratively(ThreadData *p_caller_pool_thread, T
|
|||
|
||||
_unlock_unlockable_mutexes();
|
||||
relock_unlockables = true;
|
||||
|
||||
p_caller_pool_thread->cond_var.wait(lock);
|
||||
|
||||
DEV_ASSERT(exit_threads || p_caller_pool_thread->signaled || IS_WAIT_OVER);
|
||||
p_caller_pool_thread->awaited_task = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (relock_unlockables) {
|
||||
_lock_unlockable_mutexes();
|
||||
|
@ -509,16 +524,65 @@ void WorkerThreadPool::_wait_collaboratively(ThreadData *p_caller_pool_thread, T
|
|||
}
|
||||
}
|
||||
|
||||
void WorkerThreadPool::_switch_runlevel(Runlevel p_runlevel) {
|
||||
DEV_ASSERT(p_runlevel > runlevel);
|
||||
runlevel = p_runlevel;
|
||||
memset(&runlevel_data, 0, sizeof(runlevel_data));
|
||||
for (uint32_t i = 0; i < threads.size(); i++) {
|
||||
threads[i].cond_var.notify_one();
|
||||
threads[i].signaled = true;
|
||||
}
|
||||
control_cond_var.notify_all();
|
||||
}
|
||||
|
||||
// Returns whether threads have to exit. This may perform the check about handling needed.
|
||||
bool WorkerThreadPool::_handle_runlevel(ThreadData *p_thread_data, MutexLock<BinaryMutex> &p_lock) {
|
||||
bool exit = false;
|
||||
switch (runlevel) {
|
||||
case RUNLEVEL_NORMAL: {
|
||||
} break;
|
||||
case RUNLEVEL_PRE_EXIT_LANGUAGES: {
|
||||
if (!p_thread_data->pre_exited_languages) {
|
||||
if (!task_queue.first() && !low_priority_task_queue.first()) {
|
||||
p_thread_data->pre_exited_languages = true;
|
||||
runlevel_data.pre_exit_languages.num_idle_threads++;
|
||||
control_cond_var.notify_all();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case RUNLEVEL_EXIT_LANGUAGES: {
|
||||
if (!p_thread_data->exited_languages) {
|
||||
p_lock.temp_unlock();
|
||||
ScriptServer::thread_exit();
|
||||
p_lock.temp_relock();
|
||||
p_thread_data->exited_languages = true;
|
||||
runlevel_data.exit_languages.num_exited_threads++;
|
||||
control_cond_var.notify_all();
|
||||
}
|
||||
} break;
|
||||
case RUNLEVEL_EXIT: {
|
||||
exit = true;
|
||||
} break;
|
||||
}
|
||||
return exit;
|
||||
}
|
||||
|
||||
void WorkerThreadPool::yield() {
|
||||
int th_index = get_thread_index();
|
||||
ERR_FAIL_COND_MSG(th_index == -1, "This function can only be called from a worker thread.");
|
||||
_wait_collaboratively(&threads[th_index], ThreadData::YIELDING);
|
||||
|
||||
task_mutex.lock();
|
||||
if (runlevel < RUNLEVEL_EXIT_LANGUAGES) {
|
||||
// If this long-lived task started before the scripting server was initialized,
|
||||
// now is a good time to have scripting languages ready for the current thread.
|
||||
// Otherwise, such a piece of setup won't happen unless another task has been
|
||||
// run during the collaborative wait.
|
||||
task_mutex.unlock();
|
||||
ScriptServer::thread_enter();
|
||||
} else {
|
||||
task_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void WorkerThreadPool::notify_yield_over(TaskID p_task_id) {
|
||||
|
@ -543,13 +607,13 @@ void WorkerThreadPool::notify_yield_over(TaskID p_task_id) {
|
|||
}
|
||||
|
||||
WorkerThreadPool::GroupID WorkerThreadPool::_add_group_task(const Callable &p_callable, void (*p_func)(void *, uint32_t), void *p_userdata, BaseTemplateUserdata *p_template_userdata, int p_elements, int p_tasks, bool p_high_priority, const String &p_description) {
|
||||
ERR_FAIL_COND_V_MSG(threads.is_empty(), INVALID_TASK_ID, "Can't add a group task because the WorkerThreadPool is either not initialized yet or already terminated.");
|
||||
ERR_FAIL_COND_V(p_elements < 0, INVALID_TASK_ID);
|
||||
if (p_tasks < 0) {
|
||||
p_tasks = MAX(1u, threads.size());
|
||||
}
|
||||
|
||||
task_mutex.lock();
|
||||
MutexLock<BinaryMutex> lock(task_mutex);
|
||||
|
||||
Group *group = group_allocator.alloc();
|
||||
GroupID id = last_task++;
|
||||
group->max = p_elements;
|
||||
|
@ -584,7 +648,7 @@ WorkerThreadPool::GroupID WorkerThreadPool::_add_group_task(const Callable &p_ca
|
|||
|
||||
groups[id] = group;
|
||||
|
||||
_post_tasks_and_unlock(tasks_posted, p_tasks, p_high_priority);
|
||||
_post_tasks(tasks_posted, p_tasks, p_high_priority, lock);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
@ -687,6 +751,9 @@ void WorkerThreadPool::thread_exit_unlock_allowance_zone(uint32_t p_zone_id) {
|
|||
|
||||
void WorkerThreadPool::init(int p_thread_count, float p_low_priority_task_ratio) {
|
||||
ERR_FAIL_COND(threads.size() > 0);
|
||||
|
||||
runlevel = RUNLEVEL_NORMAL;
|
||||
|
||||
if (p_thread_count < 0) {
|
||||
p_thread_count = OS::get_singleton()->get_default_thread_pool_size();
|
||||
}
|
||||
|
@ -704,6 +771,26 @@ void WorkerThreadPool::init(int p_thread_count, float p_low_priority_task_ratio)
|
|||
}
|
||||
}
|
||||
|
||||
void WorkerThreadPool::exit_languages_threads() {
|
||||
if (threads.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLock lock(task_mutex);
|
||||
|
||||
// Wait until all threads are idle.
|
||||
_switch_runlevel(RUNLEVEL_PRE_EXIT_LANGUAGES);
|
||||
while (runlevel_data.pre_exit_languages.num_idle_threads != threads.size()) {
|
||||
control_cond_var.wait(lock);
|
||||
}
|
||||
|
||||
// Wait until all threads have detached from scripting languages.
|
||||
_switch_runlevel(RUNLEVEL_EXIT_LANGUAGES);
|
||||
while (runlevel_data.exit_languages.num_exited_threads != threads.size()) {
|
||||
control_cond_var.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
void WorkerThreadPool::finish() {
|
||||
if (threads.size() == 0) {
|
||||
return;
|
||||
|
@ -716,15 +803,10 @@ void WorkerThreadPool::finish() {
|
|||
print_error("Task waiting was never re-claimed: " + E->self()->description);
|
||||
E = E->next();
|
||||
}
|
||||
|
||||
_switch_runlevel(RUNLEVEL_EXIT);
|
||||
}
|
||||
|
||||
{
|
||||
MutexLock lock(task_mutex);
|
||||
exit_threads = true;
|
||||
}
|
||||
for (ThreadData &data : threads) {
|
||||
data.cond_var.notify_one();
|
||||
}
|
||||
for (ThreadData &data : threads) {
|
||||
data.thread.wait_to_finish();
|
||||
}
|
||||
|
@ -755,5 +837,5 @@ WorkerThreadPool::WorkerThreadPool() {
|
|||
}
|
||||
|
||||
WorkerThreadPool::~WorkerThreadPool() {
|
||||
DEV_ASSERT(threads.size() == 0 && "finish() hasn't been called!");
|
||||
finish();
|
||||
}
|
||||
|
|
|
@ -114,17 +114,35 @@ private:
|
|||
Thread thread;
|
||||
bool signaled : 1;
|
||||
bool yield_is_over : 1;
|
||||
bool pre_exited_languages : 1;
|
||||
bool exited_languages : 1;
|
||||
Task *current_task = nullptr;
|
||||
Task *awaited_task = nullptr; // Null if not awaiting the condition variable, or special value (YIELDING).
|
||||
ConditionVariable cond_var;
|
||||
|
||||
ThreadData() :
|
||||
signaled(false),
|
||||
yield_is_over(false) {}
|
||||
yield_is_over(false),
|
||||
pre_exited_languages(false),
|
||||
exited_languages(false) {}
|
||||
};
|
||||
|
||||
TightLocalVector<ThreadData> threads;
|
||||
bool exit_threads = false;
|
||||
enum Runlevel {
|
||||
RUNLEVEL_NORMAL,
|
||||
RUNLEVEL_PRE_EXIT_LANGUAGES, // Block adding new tasks
|
||||
RUNLEVEL_EXIT_LANGUAGES, // All threads detach from scripting threads.
|
||||
RUNLEVEL_EXIT,
|
||||
} runlevel = RUNLEVEL_NORMAL;
|
||||
union { // Cleared on every runlevel change.
|
||||
struct {
|
||||
uint32_t num_idle_threads;
|
||||
} pre_exit_languages;
|
||||
struct {
|
||||
uint32_t num_exited_threads;
|
||||
} exit_languages;
|
||||
} runlevel_data;
|
||||
ConditionVariable control_cond_var;
|
||||
|
||||
HashMap<Thread::ID, int> thread_ids;
|
||||
HashMap<
|
||||
|
@ -152,7 +170,7 @@ private:
|
|||
|
||||
void _process_task(Task *task);
|
||||
|
||||
void _post_tasks_and_unlock(Task **p_tasks, uint32_t p_count, bool p_high_priority);
|
||||
void _post_tasks(Task **p_tasks, uint32_t p_count, bool p_high_priority, MutexLock<BinaryMutex> &p_lock);
|
||||
void _notify_threads(const ThreadData *p_current_thread_data, uint32_t p_process_count, uint32_t p_promote_count);
|
||||
|
||||
bool _try_promote_low_priority_task();
|
||||
|
@ -193,6 +211,9 @@ private:
|
|||
|
||||
void _wait_collaboratively(ThreadData *p_caller_pool_thread, Task *p_task);
|
||||
|
||||
void _switch_runlevel(Runlevel p_runlevel);
|
||||
bool _handle_runlevel(ThreadData *p_thread_data, MutexLock<BinaryMutex> &p_lock);
|
||||
|
||||
#ifdef THREADS_ENABLED
|
||||
static uint32_t _thread_enter_unlock_allowance_zone(THREADING_NAMESPACE::unique_lock<THREADING_NAMESPACE::mutex> &p_ulock);
|
||||
#endif
|
||||
|
@ -256,6 +277,7 @@ public:
|
|||
#endif
|
||||
|
||||
void init(int p_thread_count = -1, float p_low_priority_task_ratio = 0.3);
|
||||
void exit_languages_threads();
|
||||
void finish();
|
||||
WorkerThreadPool();
|
||||
~WorkerThreadPool();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -107,6 +107,8 @@ static Time *_time = nullptr;
|
|||
static core_bind::Geometry2D *_geometry_2d = nullptr;
|
||||
static core_bind::Geometry3D *_geometry_3d = nullptr;
|
||||
|
||||
static WorkerThreadPool *worker_thread_pool = nullptr;
|
||||
|
||||
extern Mutex _global_mutex;
|
||||
|
||||
static GDExtensionManager *gdextension_manager = nullptr;
|
||||
|
@ -231,6 +233,7 @@ void register_core_types() {
|
|||
|
||||
GDREGISTER_CLASS(MainLoop);
|
||||
GDREGISTER_CLASS(Translation);
|
||||
GDREGISTER_CLASS(TranslationDomain);
|
||||
GDREGISTER_CLASS(OptimizedTranslation);
|
||||
GDREGISTER_CLASS(UndoRedo);
|
||||
GDREGISTER_CLASS(TriangleMesh);
|
||||
|
@ -295,6 +298,8 @@ void register_core_types() {
|
|||
GDREGISTER_NATIVE_STRUCT(AudioFrame, "float left;float right");
|
||||
GDREGISTER_NATIVE_STRUCT(ScriptLanguageExtensionProfilingInfo, "StringName signature;uint64_t call_count;uint64_t total_time;uint64_t self_time");
|
||||
|
||||
worker_thread_pool = memnew(WorkerThreadPool);
|
||||
|
||||
OS::get_singleton()->benchmark_end_measure("Core", "Register Types");
|
||||
}
|
||||
|
||||
|
@ -345,7 +350,7 @@ void register_core_singletons() {
|
|||
Engine::get_singleton()->add_singleton(Engine::Singleton("Time", Time::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("GDExtensionManager", GDExtensionManager::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("ResourceUID", ResourceUID::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("WorkerThreadPool", WorkerThreadPool::get_singleton()));
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("WorkerThreadPool", worker_thread_pool));
|
||||
|
||||
OS::get_singleton()->benchmark_end_measure("Core", "Register Singletons");
|
||||
}
|
||||
|
@ -378,6 +383,8 @@ void unregister_core_types() {
|
|||
|
||||
// Destroy singletons in reverse order to ensure dependencies are not broken.
|
||||
|
||||
memdelete(worker_thread_pool);
|
||||
|
||||
memdelete(_engine_debugger);
|
||||
memdelete(_marshalls);
|
||||
memdelete(_classdb);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
/**************************************************************************/
|
||||
/* translation_domain.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "translation_domain.h"
|
||||
|
||||
#include "core/string/translation.h"
|
||||
#include "core/string/translation_server.h"
|
||||
|
||||
StringName TranslationDomain::get_message_from_translations(const String &p_locale, const StringName &p_message, const StringName &p_context) const {
|
||||
StringName res;
|
||||
int best_score = 0;
|
||||
|
||||
for (const Ref<Translation> &E : translations) {
|
||||
ERR_CONTINUE(E.is_null());
|
||||
int score = TranslationServer::get_singleton()->compare_locales(p_locale, E->get_locale());
|
||||
if (score > 0 && score >= best_score) {
|
||||
const StringName r = E->get_message(p_message, p_context);
|
||||
if (!r) {
|
||||
continue;
|
||||
}
|
||||
res = r;
|
||||
best_score = score;
|
||||
if (score == 10) {
|
||||
break; // Exact match, skip the rest.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
StringName TranslationDomain::get_message_from_translations(const String &p_locale, const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
|
||||
StringName res;
|
||||
int best_score = 0;
|
||||
|
||||
for (const Ref<Translation> &E : translations) {
|
||||
ERR_CONTINUE(E.is_null());
|
||||
int score = TranslationServer::get_singleton()->compare_locales(p_locale, E->get_locale());
|
||||
if (score > 0 && score >= best_score) {
|
||||
const StringName r = E->get_plural_message(p_message, p_message_plural, p_n, p_context);
|
||||
if (!r) {
|
||||
continue;
|
||||
}
|
||||
res = r;
|
||||
best_score = score;
|
||||
if (score == 10) {
|
||||
break; // Exact match, skip the rest.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
PackedStringArray TranslationDomain::get_loaded_locales() const {
|
||||
PackedStringArray locales;
|
||||
for (const Ref<Translation> &E : translations) {
|
||||
ERR_CONTINUE(E.is_null());
|
||||
locales.push_back(E->get_locale());
|
||||
}
|
||||
return locales;
|
||||
}
|
||||
|
||||
Ref<Translation> TranslationDomain::get_translation_object(const String &p_locale) const {
|
||||
Ref<Translation> res;
|
||||
int best_score = 0;
|
||||
|
||||
for (const Ref<Translation> &E : translations) {
|
||||
ERR_CONTINUE(E.is_null());
|
||||
|
||||
int score = TranslationServer::get_singleton()->compare_locales(p_locale, E->get_locale());
|
||||
if (score > 0 && score >= best_score) {
|
||||
res = E;
|
||||
best_score = score;
|
||||
if (score == 10) {
|
||||
break; // Exact match, skip the rest.
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void TranslationDomain::add_translation(const Ref<Translation> &p_translation) {
|
||||
translations.insert(p_translation);
|
||||
}
|
||||
|
||||
void TranslationDomain::remove_translation(const Ref<Translation> &p_translation) {
|
||||
translations.erase(p_translation);
|
||||
}
|
||||
|
||||
void TranslationDomain::clear() {
|
||||
translations.clear();
|
||||
}
|
||||
|
||||
StringName TranslationDomain::translate(const StringName &p_message, const StringName &p_context) const {
|
||||
const String &locale = TranslationServer::get_singleton()->get_locale();
|
||||
StringName res = get_message_from_translations(locale, p_message, p_context);
|
||||
|
||||
const String &fallback = TranslationServer::get_singleton()->get_fallback_locale();
|
||||
if (!res && fallback.length() >= 2) {
|
||||
res = get_message_from_translations(fallback, p_message, p_context);
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
return p_message;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
StringName TranslationDomain::translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
|
||||
const String &locale = TranslationServer::get_singleton()->get_locale();
|
||||
StringName res = get_message_from_translations(locale, p_message, p_message_plural, p_n, p_context);
|
||||
|
||||
const String &fallback = TranslationServer::get_singleton()->get_fallback_locale();
|
||||
if (!res && fallback.length() >= 2) {
|
||||
res = get_message_from_translations(fallback, p_message, p_message_plural, p_n, p_context);
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
if (p_n == 1) {
|
||||
return p_message;
|
||||
}
|
||||
return p_message_plural;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void TranslationDomain::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_translation_object", "locale"), &TranslationDomain::get_translation_object);
|
||||
ClassDB::bind_method(D_METHOD("add_translation", "translation"), &TranslationDomain::add_translation);
|
||||
ClassDB::bind_method(D_METHOD("remove_translation", "translation"), &TranslationDomain::remove_translation);
|
||||
ClassDB::bind_method(D_METHOD("clear"), &TranslationDomain::clear);
|
||||
ClassDB::bind_method(D_METHOD("translate", "message", "context"), &TranslationDomain::translate, DEFVAL(StringName()));
|
||||
ClassDB::bind_method(D_METHOD("translate_plural", "message", "message_plural", "n", "context"), &TranslationDomain::translate_plural, DEFVAL(StringName()));
|
||||
}
|
||||
|
||||
TranslationDomain::TranslationDomain() {
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/**************************************************************************/
|
||||
/* translation_domain.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef TRANSLATION_DOMAIN_H
|
||||
#define TRANSLATION_DOMAIN_H
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
class Translation;
|
||||
|
||||
class TranslationDomain : public RefCounted {
|
||||
GDCLASS(TranslationDomain, RefCounted);
|
||||
|
||||
HashSet<Ref<Translation>> translations;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
// Methods in this section are not intended for scripting.
|
||||
StringName get_message_from_translations(const String &p_locale, const StringName &p_message, const StringName &p_context) const;
|
||||
StringName get_message_from_translations(const String &p_locale, const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const;
|
||||
PackedStringArray get_loaded_locales() const;
|
||||
|
||||
public:
|
||||
Ref<Translation> get_translation_object(const String &p_locale) const;
|
||||
|
||||
void add_translation(const Ref<Translation> &p_translation);
|
||||
void remove_translation(const Ref<Translation> &p_translation);
|
||||
void clear();
|
||||
|
||||
StringName translate(const StringName &p_message, const StringName &p_context) const;
|
||||
StringName translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const;
|
||||
|
||||
TranslationDomain();
|
||||
};
|
||||
|
||||
#endif // TRANSLATION_DOMAIN_H
|
|
@ -404,69 +404,36 @@ String TranslationServer::get_locale() const {
|
|||
return locale;
|
||||
}
|
||||
|
||||
PackedStringArray TranslationServer::get_loaded_locales() const {
|
||||
PackedStringArray locales;
|
||||
for (const Ref<Translation> &E : translations) {
|
||||
const Ref<Translation> &t = E;
|
||||
ERR_FAIL_COND_V(t.is_null(), PackedStringArray());
|
||||
String l = t->get_locale();
|
||||
|
||||
locales.push_back(l);
|
||||
String TranslationServer::get_fallback_locale() const {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return locales;
|
||||
PackedStringArray TranslationServer::get_loaded_locales() const {
|
||||
return main_domain->get_loaded_locales();
|
||||
}
|
||||
|
||||
void TranslationServer::add_translation(const Ref<Translation> &p_translation) {
|
||||
translations.insert(p_translation);
|
||||
main_domain->add_translation(p_translation);
|
||||
}
|
||||
|
||||
void TranslationServer::remove_translation(const Ref<Translation> &p_translation) {
|
||||
translations.erase(p_translation);
|
||||
main_domain->remove_translation(p_translation);
|
||||
}
|
||||
|
||||
Ref<Translation> TranslationServer::get_translation_object(const String &p_locale) {
|
||||
Ref<Translation> res;
|
||||
int best_score = 0;
|
||||
|
||||
for (const Ref<Translation> &E : translations) {
|
||||
const Ref<Translation> &t = E;
|
||||
ERR_FAIL_COND_V(t.is_null(), nullptr);
|
||||
String l = t->get_locale();
|
||||
|
||||
int score = compare_locales(p_locale, l);
|
||||
if (score > 0 && score >= best_score) {
|
||||
res = t;
|
||||
best_score = score;
|
||||
if (score == 10) {
|
||||
break; // Exact match, skip the rest.
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
return main_domain->get_translation_object(p_locale);
|
||||
}
|
||||
|
||||
void TranslationServer::clear() {
|
||||
translations.clear();
|
||||
main_domain->clear();
|
||||
}
|
||||
|
||||
StringName TranslationServer::translate(const StringName &p_message, const StringName &p_context) const {
|
||||
// Match given message against the translation catalog for the project locale.
|
||||
|
||||
if (!enabled) {
|
||||
return p_message;
|
||||
}
|
||||
|
||||
StringName res = _get_message_from_translations(p_message, p_context, locale, false);
|
||||
|
||||
if (!res && fallback.length() >= 2) {
|
||||
res = _get_message_from_translations(p_message, p_context, fallback, false);
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
return pseudolocalization_enabled ? pseudolocalize(p_message) : p_message;
|
||||
}
|
||||
|
||||
const StringName res = main_domain->translate(p_message, p_context);
|
||||
return pseudolocalization_enabled ? pseudolocalize(res) : res;
|
||||
}
|
||||
|
||||
|
@ -478,51 +445,7 @@ StringName TranslationServer::translate_plural(const StringName &p_message, cons
|
|||
return p_message_plural;
|
||||
}
|
||||
|
||||
StringName res = _get_message_from_translations(p_message, p_context, locale, true, p_message_plural, p_n);
|
||||
|
||||
if (!res && fallback.length() >= 2) {
|
||||
res = _get_message_from_translations(p_message, p_context, fallback, true, p_message_plural, p_n);
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
if (p_n == 1) {
|
||||
return p_message;
|
||||
}
|
||||
return p_message_plural;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
StringName TranslationServer::_get_message_from_translations(const StringName &p_message, const StringName &p_context, const String &p_locale, bool plural, const String &p_message_plural, int p_n) const {
|
||||
StringName res;
|
||||
int best_score = 0;
|
||||
|
||||
for (const Ref<Translation> &E : translations) {
|
||||
const Ref<Translation> &t = E;
|
||||
ERR_FAIL_COND_V(t.is_null(), p_message);
|
||||
String l = t->get_locale();
|
||||
|
||||
int score = compare_locales(p_locale, l);
|
||||
if (score > 0 && score >= best_score) {
|
||||
StringName r;
|
||||
if (!plural) {
|
||||
r = t->get_message(p_message, p_context);
|
||||
} else {
|
||||
r = t->get_plural_message(p_message, p_message_plural, p_n, p_context);
|
||||
}
|
||||
if (!r) {
|
||||
continue;
|
||||
}
|
||||
res = r;
|
||||
best_score = score;
|
||||
if (score == 10) {
|
||||
break; // Exact match, skip the rest.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
return main_domain->translate_plural(p_message, p_message_plural, p_n, p_context);
|
||||
}
|
||||
|
||||
TranslationServer *TranslationServer::singleton = nullptr;
|
||||
|
@ -549,6 +472,34 @@ bool TranslationServer::_load_translations(const String &p_from) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TranslationServer::has_domain(const StringName &p_domain) const {
|
||||
if (p_domain == StringName()) {
|
||||
return true;
|
||||
}
|
||||
return custom_domains.has(p_domain);
|
||||
}
|
||||
|
||||
Ref<TranslationDomain> TranslationServer::get_or_add_domain(const StringName &p_domain) {
|
||||
if (p_domain == StringName()) {
|
||||
return main_domain;
|
||||
}
|
||||
const Ref<TranslationDomain> *domain = custom_domains.getptr(p_domain);
|
||||
if (domain) {
|
||||
if (domain->is_valid()) {
|
||||
return *domain;
|
||||
}
|
||||
ERR_PRINT("Bug (please report): Found invalid translation domain.");
|
||||
}
|
||||
Ref<TranslationDomain> new_domain = memnew(TranslationDomain);
|
||||
custom_domains[p_domain] = new_domain;
|
||||
return new_domain;
|
||||
}
|
||||
|
||||
void TranslationServer::remove_domain(const StringName &p_domain) {
|
||||
ERR_FAIL_COND_MSG(p_domain == StringName(), "Cannot remove main translation domain.");
|
||||
custom_domains.erase(p_domain);
|
||||
}
|
||||
|
||||
void TranslationServer::setup() {
|
||||
String test = GLOBAL_DEF("internationalization/locale/test", "");
|
||||
test = test.strip_edges();
|
||||
|
@ -574,140 +525,45 @@ void TranslationServer::setup() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void TranslationServer::set_tool_translation(const Ref<Translation> &p_translation) {
|
||||
tool_translation = p_translation;
|
||||
}
|
||||
|
||||
Ref<Translation> TranslationServer::get_tool_translation() const {
|
||||
return tool_translation;
|
||||
}
|
||||
|
||||
String TranslationServer::get_tool_locale() {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint() || Engine::get_singleton()->is_project_manager_hint()) {
|
||||
if (TranslationServer::get_singleton()->get_tool_translation().is_valid()) {
|
||||
return tool_translation->get_locale();
|
||||
} else {
|
||||
const PackedStringArray &locales = editor_domain->get_loaded_locales();
|
||||
if (locales.is_empty()) {
|
||||
return "en";
|
||||
}
|
||||
return locales[0];
|
||||
} else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
// Look for best matching loaded translation.
|
||||
String best_locale = "en";
|
||||
int best_score = 0;
|
||||
|
||||
for (const Ref<Translation> &E : translations) {
|
||||
const Ref<Translation> &t = E;
|
||||
ERR_FAIL_COND_V(t.is_null(), best_locale);
|
||||
String l = t->get_locale();
|
||||
|
||||
int score = compare_locales(locale, l);
|
||||
if (score > 0 && score >= best_score) {
|
||||
best_locale = l;
|
||||
best_score = score;
|
||||
if (score == 10) {
|
||||
break; // Exact match, skip the rest.
|
||||
Ref<Translation> t = main_domain->get_translation_object(locale);
|
||||
if (t.is_null()) {
|
||||
return "en";
|
||||
}
|
||||
}
|
||||
}
|
||||
return best_locale;
|
||||
return t->get_locale();
|
||||
}
|
||||
}
|
||||
|
||||
StringName TranslationServer::tool_translate(const StringName &p_message, const StringName &p_context) const {
|
||||
if (tool_translation.is_valid()) {
|
||||
StringName r = tool_translation->get_message(p_message, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return p_message;
|
||||
return editor_domain->translate(p_message, p_context);
|
||||
}
|
||||
|
||||
StringName TranslationServer::tool_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
|
||||
if (tool_translation.is_valid()) {
|
||||
StringName r = tool_translation->get_plural_message(p_message, p_message_plural, p_n, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_n == 1) {
|
||||
return p_message;
|
||||
}
|
||||
return p_message_plural;
|
||||
}
|
||||
|
||||
void TranslationServer::set_property_translation(const Ref<Translation> &p_translation) {
|
||||
property_translation = p_translation;
|
||||
return editor_domain->translate_plural(p_message, p_message_plural, p_n, p_context);
|
||||
}
|
||||
|
||||
StringName TranslationServer::property_translate(const StringName &p_message, const StringName &p_context) const {
|
||||
if (property_translation.is_valid()) {
|
||||
StringName r = property_translation->get_message(p_message, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return p_message;
|
||||
}
|
||||
|
||||
void TranslationServer::set_doc_translation(const Ref<Translation> &p_translation) {
|
||||
doc_translation = p_translation;
|
||||
return property_domain->translate(p_message, p_context);
|
||||
}
|
||||
|
||||
StringName TranslationServer::doc_translate(const StringName &p_message, const StringName &p_context) const {
|
||||
if (doc_translation.is_valid()) {
|
||||
StringName r = doc_translation->get_message(p_message, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return p_message;
|
||||
return doc_domain->translate(p_message, p_context);
|
||||
}
|
||||
|
||||
StringName TranslationServer::doc_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
|
||||
if (doc_translation.is_valid()) {
|
||||
StringName r = doc_translation->get_plural_message(p_message, p_message_plural, p_n, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_n == 1) {
|
||||
return p_message;
|
||||
}
|
||||
return p_message_plural;
|
||||
}
|
||||
|
||||
void TranslationServer::set_extractable_translation(const Ref<Translation> &p_translation) {
|
||||
extractable_translation = p_translation;
|
||||
}
|
||||
|
||||
StringName TranslationServer::extractable_translate(const StringName &p_message, const StringName &p_context) const {
|
||||
if (extractable_translation.is_valid()) {
|
||||
StringName r = extractable_translation->get_message(p_message, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return p_message;
|
||||
}
|
||||
|
||||
StringName TranslationServer::extractable_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context) const {
|
||||
if (extractable_translation.is_valid()) {
|
||||
StringName r = extractable_translation->get_plural_message(p_message, p_message_plural, p_n, p_context);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_n == 1) {
|
||||
return p_message;
|
||||
}
|
||||
return p_message_plural;
|
||||
return doc_domain->translate_plural(p_message, p_message_plural, p_n, p_context);
|
||||
}
|
||||
|
||||
bool TranslationServer::is_pseudolocalization_enabled() const {
|
||||
|
@ -925,6 +781,10 @@ void TranslationServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("remove_translation", "translation"), &TranslationServer::remove_translation);
|
||||
ClassDB::bind_method(D_METHOD("get_translation_object", "locale"), &TranslationServer::get_translation_object);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("has_domain", "domain"), &TranslationServer::has_domain);
|
||||
ClassDB::bind_method(D_METHOD("get_or_add_domain", "domain"), &TranslationServer::get_or_add_domain);
|
||||
ClassDB::bind_method(D_METHOD("remove_domain", "domain"), &TranslationServer::remove_domain);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("clear"), &TranslationServer::clear);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_loaded_locales"), &TranslationServer::get_loaded_locales);
|
||||
|
@ -947,5 +807,9 @@ void TranslationServer::load_translations() {
|
|||
|
||||
TranslationServer::TranslationServer() {
|
||||
singleton = this;
|
||||
main_domain.instantiate();
|
||||
editor_domain = get_or_add_domain("godot.editor");
|
||||
property_domain = get_or_add_domain("godot.properties");
|
||||
doc_domain = get_or_add_domain("godot.documentation");
|
||||
init_locale_info();
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#define TRANSLATION_SERVER_H
|
||||
|
||||
#include "core/string/translation.h"
|
||||
#include "core/string/translation_domain.h"
|
||||
|
||||
class TranslationServer : public Object {
|
||||
GDCLASS(TranslationServer, Object);
|
||||
|
@ -39,11 +40,11 @@ class TranslationServer : public Object {
|
|||
String locale = "en";
|
||||
String fallback;
|
||||
|
||||
HashSet<Ref<Translation>> translations;
|
||||
Ref<Translation> tool_translation;
|
||||
Ref<Translation> property_translation;
|
||||
Ref<Translation> doc_translation;
|
||||
Ref<Translation> extractable_translation;
|
||||
Ref<TranslationDomain> main_domain;
|
||||
Ref<TranslationDomain> editor_domain;
|
||||
Ref<TranslationDomain> property_domain;
|
||||
Ref<TranslationDomain> doc_domain;
|
||||
HashMap<StringName, Ref<TranslationDomain>> custom_domains;
|
||||
|
||||
bool enabled = true;
|
||||
|
||||
|
@ -70,8 +71,6 @@ class TranslationServer : public Object {
|
|||
bool _load_translations(const String &p_from);
|
||||
String _standardize_locale(const String &p_locale, bool p_add_defaults) const;
|
||||
|
||||
StringName _get_message_from_translations(const StringName &p_message, const StringName &p_context, const String &p_locale, bool plural, const String &p_message_plural = "", int p_n = 0) const;
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
struct LocaleScriptInfo {
|
||||
|
@ -99,6 +98,7 @@ public:
|
|||
|
||||
void set_locale(const String &p_locale);
|
||||
String get_locale() const;
|
||||
String get_fallback_locale() const;
|
||||
Ref<Translation> get_translation_object(const String &p_locale);
|
||||
|
||||
Vector<String> get_all_languages() const;
|
||||
|
@ -131,18 +131,15 @@ public:
|
|||
int compare_locales(const String &p_locale_a, const String &p_locale_b) const;
|
||||
|
||||
String get_tool_locale();
|
||||
void set_tool_translation(const Ref<Translation> &p_translation);
|
||||
Ref<Translation> get_tool_translation() const;
|
||||
StringName tool_translate(const StringName &p_message, const StringName &p_context = "") const;
|
||||
StringName tool_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const;
|
||||
void set_property_translation(const Ref<Translation> &p_translation);
|
||||
StringName property_translate(const StringName &p_message, const StringName &p_context = "") const;
|
||||
void set_doc_translation(const Ref<Translation> &p_translation);
|
||||
StringName doc_translate(const StringName &p_message, const StringName &p_context = "") const;
|
||||
StringName doc_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const;
|
||||
void set_extractable_translation(const Ref<Translation> &p_translation);
|
||||
StringName extractable_translate(const StringName &p_message, const StringName &p_context = "") const;
|
||||
StringName extractable_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const;
|
||||
|
||||
bool has_domain(const StringName &p_domain) const;
|
||||
Ref<TranslationDomain> get_or_add_domain(const StringName &p_domain);
|
||||
void remove_domain(const StringName &p_domain);
|
||||
|
||||
void setup();
|
||||
|
||||
|
|
|
@ -4626,7 +4626,7 @@ bool String::is_absolute_path() const {
|
|||
|
||||
String String::validate_ascii_identifier() const {
|
||||
if (is_empty()) {
|
||||
return "_"; // Empty string is not a valid identifier;
|
||||
return "_"; // Empty string is not a valid identifier.
|
||||
}
|
||||
|
||||
String result;
|
||||
|
@ -4647,6 +4647,29 @@ String String::validate_ascii_identifier() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
String String::validate_unicode_identifier() const {
|
||||
if (is_empty()) {
|
||||
return "_"; // Empty string is not a valid identifier.
|
||||
}
|
||||
|
||||
String result;
|
||||
if (is_unicode_identifier_start(operator[](0))) {
|
||||
result = *this;
|
||||
} else {
|
||||
result = "_" + *this;
|
||||
}
|
||||
|
||||
int len = result.length();
|
||||
char32_t *buffer = result.ptrw();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (!is_unicode_identifier_continue(buffer[i])) {
|
||||
buffer[i] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool String::is_valid_ascii_identifier() const {
|
||||
int len = length();
|
||||
|
||||
|
|
|
@ -460,6 +460,7 @@ public:
|
|||
static String get_invalid_node_name_characters(bool p_allow_internal = false);
|
||||
String validate_node_name() const;
|
||||
String validate_ascii_identifier() const;
|
||||
String validate_unicode_identifier() const;
|
||||
String validate_filename() const;
|
||||
|
||||
bool is_valid_ascii_identifier() const;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
|
|
@ -369,6 +369,34 @@ int Array::find(const Variant &p_value, int p_from) const {
|
|||
return ret;
|
||||
}
|
||||
|
||||
int Array::find_custom(const Callable &p_callable, int p_from) const {
|
||||
int ret = -1;
|
||||
|
||||
if (p_from < 0 || size() == 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
const Variant *argptrs[1];
|
||||
|
||||
for (int i = p_from; i < size(); i++) {
|
||||
const Variant &val = _p->array[i];
|
||||
argptrs[0] = &val;
|
||||
Variant res;
|
||||
Callable::CallError ce;
|
||||
p_callable.callp(argptrs, 1, res, ce);
|
||||
if (unlikely(ce.error != Callable::CallError::CALL_OK)) {
|
||||
ERR_FAIL_V_MSG(ret, "Error calling method from 'find_custom': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V_MSG(res.get_type() != Variant::Type::BOOL, ret, "Error on method from 'find_custom': Return type of callable must be boolean.");
|
||||
if (res.operator bool()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Array::rfind(const Variant &p_value, int p_from) const {
|
||||
if (_p->array.size() == 0) {
|
||||
return -1;
|
||||
|
@ -394,6 +422,41 @@ int Array::rfind(const Variant &p_value, int p_from) const {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int Array::rfind_custom(const Callable &p_callable, int p_from) const {
|
||||
if (_p->array.size() == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (p_from < 0) {
|
||||
// Relative offset from the end.
|
||||
p_from = _p->array.size() + p_from;
|
||||
}
|
||||
if (p_from < 0 || p_from >= _p->array.size()) {
|
||||
// Limit to array boundaries.
|
||||
p_from = _p->array.size() - 1;
|
||||
}
|
||||
|
||||
const Variant *argptrs[1];
|
||||
|
||||
for (int i = p_from; i >= 0; i--) {
|
||||
const Variant &val = _p->array[i];
|
||||
argptrs[0] = &val;
|
||||
Variant res;
|
||||
Callable::CallError ce;
|
||||
p_callable.callp(argptrs, 1, res, ce);
|
||||
if (unlikely(ce.error != Callable::CallError::CALL_OK)) {
|
||||
ERR_FAIL_V_MSG(-1, "Error calling method from 'rfind_custom': " + Variant::get_callable_error_text(p_callable, argptrs, 1, ce));
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V_MSG(res.get_type() != Variant::Type::BOOL, -1, "Error on method from 'rfind_custom': Return type of callable must be boolean.");
|
||||
if (res.operator bool()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Array::count(const Variant &p_value) const {
|
||||
Variant value = p_value;
|
||||
ERR_FAIL_COND_V(!_p->typed.validate(value, "count"), 0);
|
||||
|
@ -761,7 +824,7 @@ Variant Array::max() const {
|
|||
return Variant(); //not a valid comparison
|
||||
}
|
||||
if (bool(ret)) {
|
||||
//is less
|
||||
//is greater
|
||||
maxval = test;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,7 +152,9 @@ public:
|
|||
void reverse();
|
||||
|
||||
int find(const Variant &p_value, int p_from = 0) const;
|
||||
int find_custom(const Callable &p_callable, int p_from = 0) const;
|
||||
int rfind(const Variant &p_value, int p_from = -1) const;
|
||||
int rfind_custom(const Callable &p_callable, int p_from = -1) const;
|
||||
int count(const Variant &p_value) const;
|
||||
bool has(const Variant &p_value) const;
|
||||
|
||||
|
|
|
@ -466,7 +466,7 @@ void call_with_variant_argsc(T *p_instance, void (T::*p_method)(P...) const, con
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
call_with_variant_args_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
call_with_variant_argsc_helper<T, P...>(p_instance, p_method, p_args, r_error, BuildIndexSequence<sizeof...(P)>{});
|
||||
}
|
||||
|
||||
template <typename T, typename... P>
|
||||
|
@ -830,7 +830,7 @@ void call_with_variant_args_static_ret(R (*p_method)(P...), const Variant **p_ar
|
|||
}
|
||||
|
||||
template <typename... P>
|
||||
void call_with_variant_args_static_ret(void (*p_method)(P...), const Variant **p_args, int p_argcount, Variant &r_ret, Callable::CallError &r_error) {
|
||||
void call_with_variant_args_static(void (*p_method)(P...), const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
if ((size_t)p_argcount > sizeof...(P)) {
|
||||
r_error.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
|
||||
|
|
|
@ -545,6 +545,13 @@ bool Signal::is_connected(const Callable &p_callable) const {
|
|||
return obj->is_connected(name, p_callable);
|
||||
}
|
||||
|
||||
bool Signal::has_connections() const {
|
||||
Object *obj = get_object();
|
||||
ERR_FAIL_NULL_V(obj, false);
|
||||
|
||||
return obj->has_connections(name);
|
||||
}
|
||||
|
||||
Array Signal::get_connections() const {
|
||||
Object *obj = get_object();
|
||||
if (!obj) {
|
||||
|
|
|
@ -192,6 +192,7 @@ public:
|
|||
Error connect(const Callable &p_callable, uint32_t p_flags = 0);
|
||||
void disconnect(const Callable &p_callable);
|
||||
bool is_connected(const Callable &p_callable) const;
|
||||
bool has_connections() const;
|
||||
|
||||
Array get_connections() const;
|
||||
Signal(const Object *p_object, const StringName &p_name);
|
||||
|
|
|
@ -83,35 +83,64 @@ Variant Dictionary::get_value_at_index(int p_index) const {
|
|||
return Variant();
|
||||
}
|
||||
|
||||
// WARNING: This operator does not validate the value type. For scripting/extensions this is
|
||||
// done in `variant_setget.cpp`. Consider using `set()` if the data might be invalid.
|
||||
Variant &Dictionary::operator[](const Variant &p_key) {
|
||||
if (unlikely(_p->read_only)) {
|
||||
if (likely(_p->variant_map.has(p_key))) {
|
||||
*_p->read_only = _p->variant_map[p_key];
|
||||
} else {
|
||||
*_p->read_only = Variant();
|
||||
Variant key = p_key;
|
||||
if (unlikely(!_p->typed_key.validate(key, "use `operator[]`"))) {
|
||||
if (unlikely(!_p->typed_fallback)) {
|
||||
_p->typed_fallback = memnew(Variant);
|
||||
}
|
||||
VariantInternal::initialize(_p->typed_fallback, _p->typed_value.type);
|
||||
return *_p->typed_fallback;
|
||||
} else if (unlikely(_p->read_only)) {
|
||||
if (likely(_p->variant_map.has(key))) {
|
||||
*_p->read_only = _p->variant_map[key];
|
||||
} else {
|
||||
VariantInternal::initialize(_p->read_only, _p->typed_value.type);
|
||||
}
|
||||
|
||||
return *_p->read_only;
|
||||
} else {
|
||||
return _p->variant_map[p_key];
|
||||
if (unlikely(!_p->variant_map.has(key))) {
|
||||
VariantInternal::initialize(&_p->variant_map[key], _p->typed_value.type);
|
||||
}
|
||||
return _p->variant_map[key];
|
||||
}
|
||||
}
|
||||
|
||||
const Variant &Dictionary::operator[](const Variant &p_key) const {
|
||||
// Will not insert key, so no conversion is necessary.
|
||||
return _p->variant_map[p_key];
|
||||
Variant key = p_key;
|
||||
if (unlikely(!_p->typed_key.validate(key, "use `operator[]`"))) {
|
||||
if (unlikely(!_p->typed_fallback)) {
|
||||
_p->typed_fallback = memnew(Variant);
|
||||
}
|
||||
VariantInternal::initialize(_p->typed_fallback, _p->typed_value.type);
|
||||
return *_p->typed_fallback;
|
||||
} else {
|
||||
// Will not insert key, so no initialization is necessary.
|
||||
return _p->variant_map[key];
|
||||
}
|
||||
}
|
||||
|
||||
const Variant *Dictionary::getptr(const Variant &p_key) const {
|
||||
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(p_key));
|
||||
Variant key = p_key;
|
||||
if (unlikely(!_p->typed_key.validate(key, "getptr"))) {
|
||||
return nullptr;
|
||||
}
|
||||
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(key));
|
||||
if (!E) {
|
||||
return nullptr;
|
||||
}
|
||||
return &E->value;
|
||||
}
|
||||
|
||||
// WARNING: This method does not validate the value type.
|
||||
Variant *Dictionary::getptr(const Variant &p_key) {
|
||||
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::Iterator E(_p->variant_map.find(p_key));
|
||||
Variant key = p_key;
|
||||
if (unlikely(!_p->typed_key.validate(key, "getptr"))) {
|
||||
return nullptr;
|
||||
}
|
||||
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::Iterator E(_p->variant_map.find(key));
|
||||
if (!E) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -158,6 +187,16 @@ Variant Dictionary::get_or_add(const Variant &p_key, const Variant &p_default) {
|
|||
return *result;
|
||||
}
|
||||
|
||||
bool Dictionary::set(const Variant &p_key, const Variant &p_value) {
|
||||
ERR_FAIL_COND_V_MSG(_p->read_only, false, "Dictionary is in read-only state.");
|
||||
Variant key = p_key;
|
||||
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "set"), false);
|
||||
Variant value = p_value;
|
||||
ERR_FAIL_COND_V(!_p->typed_value.validate(value, "set"), false);
|
||||
_p->variant_map[key] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
int Dictionary::size() const {
|
||||
return _p->variant_map.size();
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ public:
|
|||
Variant get_valid(const Variant &p_key) const;
|
||||
Variant get(const Variant &p_key, const Variant &p_default) const;
|
||||
Variant get_or_add(const Variant &p_key, const Variant &p_default);
|
||||
bool set(const Variant &p_key, const Variant &p_value);
|
||||
|
||||
int size() const;
|
||||
bool is_empty() const;
|
||||
|
|
|
@ -657,7 +657,23 @@ static _FORCE_INLINE_ void vc_ptrcall(void (*method)(T *, P...), void *p_base, c
|
|||
} \
|
||||
};
|
||||
|
||||
#define VARCALL_PACKED_GETTER(m_packed_type, m_return_type) \
|
||||
static m_return_type func_##m_packed_type##_get(m_packed_type *p_instance, int64_t p_index) { \
|
||||
return p_instance->get(p_index); \
|
||||
}
|
||||
|
||||
struct _VariantCall {
|
||||
VARCALL_PACKED_GETTER(PackedByteArray, uint8_t)
|
||||
VARCALL_PACKED_GETTER(PackedColorArray, Color)
|
||||
VARCALL_PACKED_GETTER(PackedFloat32Array, float)
|
||||
VARCALL_PACKED_GETTER(PackedFloat64Array, double)
|
||||
VARCALL_PACKED_GETTER(PackedInt32Array, int32_t)
|
||||
VARCALL_PACKED_GETTER(PackedInt64Array, int64_t)
|
||||
VARCALL_PACKED_GETTER(PackedStringArray, String)
|
||||
VARCALL_PACKED_GETTER(PackedVector2Array, Vector2)
|
||||
VARCALL_PACKED_GETTER(PackedVector3Array, Vector3)
|
||||
VARCALL_PACKED_GETTER(PackedVector4Array, Vector4)
|
||||
|
||||
static String func_PackedByteArray_get_string_from_ascii(PackedByteArray *p_instance) {
|
||||
String s;
|
||||
if (p_instance->size() > 0) {
|
||||
|
@ -2121,6 +2137,7 @@ static void _register_variant_builtin_methods_misc() {
|
|||
bind_method(Signal, disconnect, sarray("callable"), varray());
|
||||
bind_method(Signal, is_connected, sarray("callable"), varray());
|
||||
bind_method(Signal, get_connections, sarray(), varray());
|
||||
bind_method(Signal, has_connections, sarray(), varray());
|
||||
|
||||
bind_custom(Signal, emit, _VariantCall::func_Signal_emit, false, Variant);
|
||||
|
||||
|
@ -2267,6 +2284,7 @@ static void _register_variant_builtin_methods_misc() {
|
|||
bind_method(Dictionary, duplicate, sarray("deep"), varray(false));
|
||||
bind_method(Dictionary, get, sarray("key", "default"), varray(Variant()));
|
||||
bind_method(Dictionary, get_or_add, sarray("key", "default"), varray(Variant()));
|
||||
bind_method(Dictionary, set, sarray("key", "value"), varray());
|
||||
bind_method(Dictionary, is_typed, sarray(), varray());
|
||||
bind_method(Dictionary, is_typed_key, sarray(), varray());
|
||||
bind_method(Dictionary, is_typed_value, sarray(), varray());
|
||||
|
@ -2292,6 +2310,8 @@ static void _register_variant_builtin_methods_array() {
|
|||
bind_method(Array, clear, sarray(), varray());
|
||||
bind_method(Array, hash, sarray(), varray());
|
||||
bind_method(Array, assign, sarray("array"), varray());
|
||||
bind_method(Array, get, sarray("index"), varray());
|
||||
bind_method(Array, set, sarray("index", "value"), varray());
|
||||
bind_method(Array, push_back, sarray("value"), varray());
|
||||
bind_method(Array, push_front, sarray("value"), varray());
|
||||
bind_method(Array, append, sarray("value"), varray());
|
||||
|
@ -2305,7 +2325,9 @@ static void _register_variant_builtin_methods_array() {
|
|||
bind_method(Array, back, sarray(), varray());
|
||||
bind_method(Array, pick_random, sarray(), varray());
|
||||
bind_method(Array, find, sarray("what", "from"), varray(0));
|
||||
bind_method(Array, find_custom, sarray("method", "from"), varray(0));
|
||||
bind_method(Array, rfind, sarray("what", "from"), varray(-1));
|
||||
bind_method(Array, rfind_custom, sarray("method", "from"), varray(-1));
|
||||
bind_method(Array, count, sarray("value"), varray());
|
||||
bind_method(Array, has, sarray("value"), varray());
|
||||
bind_method(Array, pop_back, sarray(), varray());
|
||||
|
@ -2334,6 +2356,18 @@ static void _register_variant_builtin_methods_array() {
|
|||
bind_method(Array, make_read_only, sarray(), varray());
|
||||
bind_method(Array, is_read_only, sarray(), varray());
|
||||
|
||||
/* Packed*Array get (see VARCALL_PACKED_GETTER macro) */
|
||||
bind_function(PackedByteArray, get, _VariantCall::func_PackedByteArray_get, sarray("index"), varray());
|
||||
bind_function(PackedColorArray, get, _VariantCall::func_PackedColorArray_get, sarray("index"), varray());
|
||||
bind_function(PackedFloat32Array, get, _VariantCall::func_PackedFloat32Array_get, sarray("index"), varray());
|
||||
bind_function(PackedFloat64Array, get, _VariantCall::func_PackedFloat64Array_get, sarray("index"), varray());
|
||||
bind_function(PackedInt32Array, get, _VariantCall::func_PackedInt32Array_get, sarray("index"), varray());
|
||||
bind_function(PackedInt64Array, get, _VariantCall::func_PackedInt64Array_get, sarray("index"), varray());
|
||||
bind_function(PackedStringArray, get, _VariantCall::func_PackedStringArray_get, sarray("index"), varray());
|
||||
bind_function(PackedVector2Array, get, _VariantCall::func_PackedVector2Array_get, sarray("index"), varray());
|
||||
bind_function(PackedVector3Array, get, _VariantCall::func_PackedVector3Array_get, sarray("index"), varray());
|
||||
bind_function(PackedVector4Array, get, _VariantCall::func_PackedVector4Array_get, sarray("index"), varray());
|
||||
|
||||
/* Byte Array */
|
||||
bind_method(PackedByteArray, size, sarray(), varray());
|
||||
bind_method(PackedByteArray, is_empty, sarray(), varray());
|
||||
|
|
|
@ -923,7 +923,10 @@ public:
|
|||
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
|
||||
bool valid = true;
|
||||
String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), &valid);
|
||||
ERR_FAIL_COND_MSG(!valid, result);
|
||||
if (unlikely(!valid)) {
|
||||
*VariantGetInternalPtr<String>::get_ptr(r_ret) = *VariantGetInternalPtr<S>::get_ptr(left);
|
||||
ERR_FAIL_MSG(vformat("String formatting error: %s.", result));
|
||||
}
|
||||
*VariantGetInternalPtr<String>::get_ptr(r_ret) = result;
|
||||
}
|
||||
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
|
||||
|
@ -948,7 +951,10 @@ public:
|
|||
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
|
||||
bool valid = true;
|
||||
String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), *VariantGetInternalPtr<Array>::get_ptr(right), &valid);
|
||||
ERR_FAIL_COND_MSG(!valid, result);
|
||||
if (unlikely(!valid)) {
|
||||
*VariantGetInternalPtr<String>::get_ptr(r_ret) = *VariantGetInternalPtr<S>::get_ptr(left);
|
||||
ERR_FAIL_MSG(vformat("String formatting error: %s.", result));
|
||||
}
|
||||
*VariantGetInternalPtr<String>::get_ptr(r_ret) = result;
|
||||
}
|
||||
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
|
||||
|
@ -976,7 +982,10 @@ public:
|
|||
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
|
||||
bool valid = true;
|
||||
String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), right->get_validated_object(), &valid);
|
||||
ERR_FAIL_COND_MSG(!valid, result);
|
||||
if (unlikely(!valid)) {
|
||||
*VariantGetInternalPtr<String>::get_ptr(r_ret) = *VariantGetInternalPtr<S>::get_ptr(left);
|
||||
ERR_FAIL_MSG(vformat("String formatting error: %s.", result));
|
||||
}
|
||||
*VariantGetInternalPtr<String>::get_ptr(r_ret) = result;
|
||||
}
|
||||
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
|
||||
|
@ -1003,7 +1012,10 @@ public:
|
|||
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
|
||||
bool valid = true;
|
||||
String result = do_mod(*VariantGetInternalPtr<S>::get_ptr(left), *VariantGetInternalPtr<T>::get_ptr(right), &valid);
|
||||
ERR_FAIL_COND_MSG(!valid, result);
|
||||
if (unlikely(!valid)) {
|
||||
*VariantGetInternalPtr<String>::get_ptr(r_ret) = *VariantGetInternalPtr<S>::get_ptr(left);
|
||||
ERR_FAIL_MSG(vformat("String formatting error: %s.", result));
|
||||
}
|
||||
*VariantGetInternalPtr<String>::get_ptr(r_ret) = result;
|
||||
}
|
||||
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
|
||||
|
@ -1492,7 +1504,10 @@ public:
|
|||
}
|
||||
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
|
||||
Object *l = right->get_validated_object();
|
||||
ERR_FAIL_NULL(l);
|
||||
if (unlikely(!l)) {
|
||||
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = false;
|
||||
ERR_FAIL_MSG("Invalid base object for 'in'.");
|
||||
}
|
||||
const String &a = *VariantGetInternalPtr<String>::get_ptr(left);
|
||||
|
||||
bool valid;
|
||||
|
@ -1526,7 +1541,10 @@ public:
|
|||
}
|
||||
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
|
||||
Object *l = right->get_validated_object();
|
||||
ERR_FAIL_NULL(l);
|
||||
if (unlikely(!l)) {
|
||||
*VariantGetInternalPtr<bool>::get_ptr(r_ret) = false;
|
||||
ERR_FAIL_MSG("Invalid base object for 'in'.");
|
||||
}
|
||||
const StringName &a = *VariantGetInternalPtr<StringName>::get_ptr(left);
|
||||
|
||||
bool valid;
|
||||
|
|
|
@ -252,20 +252,7 @@ void Variant::set_named(const StringName &p_member, const Variant &p_value, bool
|
|||
}
|
||||
} else if (type == Variant::DICTIONARY) {
|
||||
Dictionary &dict = *VariantGetInternalPtr<Dictionary>::get_ptr(this);
|
||||
|
||||
if (dict.is_read_only()) {
|
||||
r_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Variant *v = dict.getptr(p_member);
|
||||
if (v) {
|
||||
*v = p_value;
|
||||
} else {
|
||||
dict[p_member] = p_value;
|
||||
}
|
||||
|
||||
r_valid = true;
|
||||
r_valid = dict.set(p_member, p_value);
|
||||
} else {
|
||||
r_valid = false;
|
||||
}
|
||||
|
@ -721,26 +708,16 @@ struct VariantIndexedSetGet_Dictionary {
|
|||
PtrToArg<Variant>::encode(*ptr, member);
|
||||
}
|
||||
static void set(Variant *base, int64_t index, const Variant *value, bool *valid, bool *oob) {
|
||||
if (VariantGetInternalPtr<Dictionary>::get_ptr(base)->is_read_only()) {
|
||||
*valid = false;
|
||||
*oob = true;
|
||||
return;
|
||||
}
|
||||
(*VariantGetInternalPtr<Dictionary>::get_ptr(base))[index] = *value;
|
||||
*oob = false;
|
||||
*valid = true;
|
||||
*valid = VariantGetInternalPtr<Dictionary>::get_ptr(base)->set(index, *value);
|
||||
*oob = VariantGetInternalPtr<Dictionary>::get_ptr(base)->is_read_only();
|
||||
}
|
||||
static void validated_set(Variant *base, int64_t index, const Variant *value, bool *oob) {
|
||||
if (VariantGetInternalPtr<Dictionary>::get_ptr(base)->is_read_only()) {
|
||||
*oob = true;
|
||||
return;
|
||||
}
|
||||
(*VariantGetInternalPtr<Dictionary>::get_ptr(base))[index] = *value;
|
||||
*oob = false;
|
||||
VariantGetInternalPtr<Dictionary>::get_ptr(base)->set(index, *value);
|
||||
*oob = VariantGetInternalPtr<Dictionary>::get_ptr(base)->is_read_only();
|
||||
}
|
||||
static void ptr_set(void *base, int64_t index, const void *member) {
|
||||
Dictionary &v = *reinterpret_cast<Dictionary *>(base);
|
||||
v[index] = PtrToArg<Variant>::convert(member);
|
||||
v.set(index, PtrToArg<Variant>::convert(member));
|
||||
}
|
||||
static Variant::Type get_index_type() { return Variant::NIL; }
|
||||
static uint32_t get_index_usage() { return PROPERTY_USAGE_DEFAULT; }
|
||||
|
@ -1010,16 +987,11 @@ struct VariantKeyedSetGetDictionary {
|
|||
PtrToArg<Variant>::encode(*ptr, value);
|
||||
}
|
||||
static void set(Variant *base, const Variant *key, const Variant *value, bool *r_valid) {
|
||||
if (VariantGetInternalPtr<Dictionary>::get_ptr(base)->is_read_only()) {
|
||||
*r_valid = false;
|
||||
return;
|
||||
}
|
||||
(*VariantGetInternalPtr<Dictionary>::get_ptr(base))[*key] = *value;
|
||||
*r_valid = true;
|
||||
*r_valid = VariantGetInternalPtr<Dictionary>::get_ptr(base)->set(*key, *value);
|
||||
}
|
||||
static void ptr_set(void *base, const void *key, const void *value) {
|
||||
Dictionary &v = *reinterpret_cast<Dictionary *>(base);
|
||||
v[PtrToArg<Variant>::convert(key)] = PtrToArg<Variant>::convert(value);
|
||||
v.set(PtrToArg<Variant>::convert(key), PtrToArg<Variant>::convert(value));
|
||||
}
|
||||
|
||||
static bool has(const Variant *base, const Variant *key, bool *r_valid) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue