Merge branch 'godotengine:master' into master
This commit is contained in:
commit
d4ca15c458
311
.clang-format
311
.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 ###
|
||||
BasedOnStyle: LLVM
|
||||
# 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
|
||||
AlignOperands: DontAlign
|
||||
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,50 +61,49 @@ AllowAllParametersOfDeclarationOnNextLine: false
|
|||
# - __capability
|
||||
# BinPackArguments: true
|
||||
# BinPackParameters: true
|
||||
# BitFieldColonSpacing: Both
|
||||
# BraceWrapping:
|
||||
# AfterCaseLabel: false
|
||||
# AfterClass: false
|
||||
# AfterCaseLabel: false
|
||||
# AfterClass: false
|
||||
# AfterControlStatement: Never
|
||||
# AfterEnum: false
|
||||
# AfterFunction: false
|
||||
# AfterNamespace: false
|
||||
# AfterEnum: false
|
||||
# AfterFunction: false
|
||||
# AfterNamespace: false
|
||||
# AfterObjCDeclaration: false
|
||||
# AfterStruct: false
|
||||
# AfterUnion: false
|
||||
# AfterStruct: false
|
||||
# AfterUnion: false
|
||||
# AfterExternBlock: false
|
||||
# BeforeCatch: false
|
||||
# BeforeElse: false
|
||||
# BeforeCatch: false
|
||||
# BeforeElse: false
|
||||
# BeforeLambdaBody: false
|
||||
# BeforeWhile: false
|
||||
# IndentBraces: false
|
||||
# BeforeWhile: false
|
||||
# IndentBraces: false
|
||||
# SplitEmptyFunction: true
|
||||
# SplitEmptyRecord: true
|
||||
# SplitEmptyNamespace: true
|
||||
# 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
|
||||
ColumnLimit: 0
|
||||
# CommentPragmas: '^ IWYU pragma:'
|
||||
# CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
# DeriveLineEnding: true
|
||||
# DerivePointerAlignment: false
|
||||
# DisableFormat: false
|
||||
# DisableFormat: false
|
||||
# EmptyLineAfterAccessModifier: Never
|
||||
# EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
# ExperimentalAutoDetectBinPacking: false
|
||||
# PackConstructorInitializers: BinPack
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
# AllowAllConstructorInitializersOnNextLine: true
|
||||
# FixNamespaceComments: true
|
||||
# ForEachMacros:
|
||||
# - foreach
|
||||
|
@ -82,118 +111,138 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
|||
# - BOOST_FOREACH
|
||||
# IfMacros:
|
||||
# - KJ_IF_MAYBE
|
||||
# IncludeBlocks: Preserve
|
||||
# IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '".*"'
|
||||
Priority: 1
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 2
|
||||
- Regex: '^<.*'
|
||||
Priority: 3
|
||||
# IncludeIsMainRegex: '(Test)?$'
|
||||
- Regex: ^".*"$
|
||||
Priority: 1
|
||||
- Regex: ^<.*\.h>$
|
||||
Priority: 2
|
||||
- Regex: ^<.*>$
|
||||
Priority: 3
|
||||
# IncludeIsMainRegex: (Test)?$
|
||||
# IncludeIsMainSourceRegex: ''
|
||||
# IndentAccessModifiers: false
|
||||
IndentCaseLabels: true
|
||||
# IndentCaseBlocks: false
|
||||
IndentCaseLabels: true
|
||||
# IndentExternBlock: AfterExternBlock
|
||||
# IndentGotoLabels: true
|
||||
# IndentPPDirectives: None
|
||||
# IndentExternBlock: AfterExternBlock
|
||||
# IndentRequires: false
|
||||
IndentWidth: 4
|
||||
# IndentRequiresClause: true
|
||||
IndentWidth: 4
|
||||
# IndentWrappedFunctionNames: false
|
||||
# InsertBraces: 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: ''
|
||||
# MacroBlockEnd: ''
|
||||
# MaxEmptyLinesToKeep: 1
|
||||
# NamespaceIndentation: None
|
||||
# PenaltyBreakAssignment: 2
|
||||
# PenaltyBreakBeforeFirstCallParameter: 19
|
||||
# PenaltyBreakComment: 300
|
||||
# PenaltyBreakFirstLessLess: 120
|
||||
# PenaltyBreakOpenParenthesis: 0
|
||||
# PenaltyBreakString: 1000
|
||||
# PenaltyBreakTemplateDeclaration: 10
|
||||
# PenaltyExcessCharacter: 1000000
|
||||
# PenaltyReturnTypeOnItsOwnLine: 60
|
||||
# PenaltyIndentedWhitespace: 0
|
||||
# PointerAlignment: Right
|
||||
# PPIndentWidth: -1
|
||||
# ReferenceAlignment: Pointer
|
||||
# ReflowComments: true
|
||||
# RemoveBracesLLVM: false
|
||||
# SeparateDefinitionBlocks: Leave
|
||||
# ShortNamespaceLines: 1
|
||||
# SortIncludes: CaseSensitive
|
||||
# SortJavaStaticImport: Before
|
||||
# SortUsingDeclarations: true
|
||||
# SpaceAfterCStyleCast: false
|
||||
# SpaceAfterLogicalNot: false
|
||||
# SpaceAfterTemplateKeyword: true
|
||||
# SpaceBeforeAssignmentOperators: true
|
||||
# SpaceBeforeCaseColon: false
|
||||
# SpaceBeforeCpp11BracedList: false
|
||||
# SpaceBeforeCtorInitializerColon: true
|
||||
# SpaceBeforeInheritanceColon: true
|
||||
# SpaceBeforeParens: ControlStatements
|
||||
# SpaceBeforeParensOptions:
|
||||
# AfterControlStatements: true
|
||||
# AfterForeachMacros: true
|
||||
# AfterFunctionDefinitionName: false
|
||||
# AfterFunctionDeclarationName: false
|
||||
# AfterIfMacros: true
|
||||
# AfterOverloadedOperator: false
|
||||
# BeforeNonEmptyParentheses: false
|
||||
# SpaceAroundPointerQualifiers: Default
|
||||
# SpaceBeforeRangeBasedForLoopColon: true
|
||||
# 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
|
||||
# SpacesInSquareBrackets: false
|
||||
# SpaceBeforeSquareBrackets: false
|
||||
# BitFieldColonSpacing: Both
|
||||
# StatementAttributeLikeMacros:
|
||||
# - Q_EMIT
|
||||
# StatementMacros:
|
||||
# - Q_UNUSED
|
||||
# - QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
# UseCRLF: false
|
||||
UseTab: Always
|
||||
# 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']
|
||||
...
|
||||
# PPIndentWidth: -1
|
||||
PackConstructorInitializers: NextLine
|
||||
# PenaltyBreakAssignment: 2
|
||||
# PenaltyBreakBeforeFirstCallParameter: 19
|
||||
# PenaltyBreakComment: 300
|
||||
# PenaltyBreakFirstLessLess: 120
|
||||
# PenaltyBreakOpenParenthesis: 0
|
||||
# PenaltyBreakScopeResolution: 500
|
||||
# PenaltyBreakString: 1000
|
||||
# PenaltyBreakTemplateDeclaration: 10
|
||||
# PenaltyExcessCharacter: 1000000
|
||||
# PenaltyIndentedWhitespace: 0
|
||||
# PenaltyReturnTypeOnItsOwnLine: 60
|
||||
# PointerAlignment: Right
|
||||
# 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: LexicographicNumeric
|
||||
# SpaceAfterCStyleCast: false
|
||||
# SpaceAfterLogicalNot: false
|
||||
# SpaceAfterTemplateKeyword: true
|
||||
# SpaceAroundPointerQualifiers: Default
|
||||
# SpaceBeforeAssignmentOperators: true
|
||||
# SpaceBeforeCaseColon: false
|
||||
# SpaceBeforeCpp11BracedList: false
|
||||
# SpaceBeforeCtorInitializerColon: true
|
||||
# SpaceBeforeInheritanceColon: true
|
||||
# SpaceBeforeJsonColon: false
|
||||
# SpaceBeforeParensOptions:
|
||||
# AfterControlStatements: true
|
||||
# AfterForeachMacros: true
|
||||
# AfterFunctionDeclarationName: false
|
||||
# AfterFunctionDefinitionName: false
|
||||
# AfterIfMacros: true
|
||||
# AfterOverloadedOperator: false
|
||||
# AfterPlacementOperator: true
|
||||
# AfterRequiresInClause: false
|
||||
# AfterRequiresInExpression: false
|
||||
# BeforeNonEmptyParentheses: false
|
||||
# SpaceBeforeRangeBasedForLoopColon: true
|
||||
# SpaceBeforeSquareBrackets: false
|
||||
# SpaceInEmptyBlock: false
|
||||
# SpacesBeforeTrailingComments: 1
|
||||
# SpacesInAngles: Never
|
||||
# SpacesInContainerLiterals: true
|
||||
## 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
|
||||
# SpacesInParens: Never
|
||||
# SpacesInParensOptions:
|
||||
# InConditionalStatements: false
|
||||
# InCStyleCasts: false
|
||||
# InEmptyParentheses: false
|
||||
# Other: false
|
||||
# SpacesInSquareBrackets: false
|
||||
Standard: c++17
|
||||
# StatementAttributeLikeMacros:
|
||||
# - Q_EMIT
|
||||
# StatementMacros:
|
||||
# - Q_UNUSED
|
||||
# - QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
UseTab: Always
|
||||
# VerilogBreakBetweenInstancePorts: true
|
||||
# WhitespaceSensitiveMacros:
|
||||
# - BOOST_PP_STRINGIZE
|
||||
# - CF_SWIFT_NAME
|
||||
# - 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,180 +4,234 @@
|
|||
|
||||
# Buildsystem
|
||||
|
||||
.* @godotengine/buildsystem
|
||||
.github/ @godotengine/buildsystem
|
||||
*.py @godotengine/buildsystem
|
||||
SConstruct @godotengine/buildsystem
|
||||
SCsub @godotengine/buildsystem
|
||||
* @godotengine/buildsystem
|
||||
|
||||
# Core
|
||||
|
||||
/core/ @godotengine/core
|
||||
/core/crypto/ @godotengine/network
|
||||
/core/debugger/ @godotengine/debugger
|
||||
/core/extension/ @godotengine/gdextension
|
||||
/core/input/ @godotengine/input
|
||||
/core/ @godotengine/core
|
||||
/core/crypto/ @godotengine/network
|
||||
/core/debugger/ @godotengine/debugger
|
||||
/core/extension/ @godotengine/gdextension
|
||||
/core/input/ @godotengine/input
|
||||
|
||||
# Doc
|
||||
|
||||
/doc/ @godotengine/documentation
|
||||
doc_classes/* @godotengine/documentation
|
||||
/doc/ @godotengine/documentation
|
||||
**/doc_classes/ @godotengine/documentation
|
||||
|
||||
# Drivers
|
||||
|
||||
## Audio
|
||||
/drivers/alsa/ @godotengine/audio
|
||||
/drivers/alsamidi/ @godotengine/audio
|
||||
/drivers/coreaudio/ @godotengine/audio
|
||||
/drivers/coremidi/ @godotengine/audio
|
||||
/drivers/pulseaudio/ @godotengine/audio
|
||||
/drivers/wasapi/ @godotengine/audio
|
||||
/drivers/winmidi/ @godotengine/audio
|
||||
/drivers/xaudio2/ @godotengine/audio
|
||||
/drivers/alsa/ @godotengine/audio
|
||||
/drivers/alsamidi/ @godotengine/audio
|
||||
/drivers/coreaudio/ @godotengine/audio
|
||||
/drivers/coremidi/ @godotengine/audio
|
||||
/drivers/pulseaudio/ @godotengine/audio
|
||||
/drivers/wasapi/ @godotengine/audio
|
||||
/drivers/winmidi/ @godotengine/audio
|
||||
/drivers/xaudio2/ @godotengine/audio
|
||||
|
||||
## Rendering
|
||||
/drivers/d3d12/ @godotengine/rendering
|
||||
/drivers/dummy/ @godotengine/rendering
|
||||
/drivers/gles3/ @godotengine/rendering
|
||||
/drivers/spirv-reflect/ @godotengine/rendering
|
||||
/drivers/vulkan/ @godotengine/rendering
|
||||
/drivers/d3d12/ @godotengine/rendering
|
||||
/drivers/dummy/ @godotengine/rendering
|
||||
/drivers/gles3/ @godotengine/rendering
|
||||
/drivers/spirv-reflect/ @godotengine/rendering
|
||||
/drivers/vulkan/ @godotengine/rendering
|
||||
|
||||
## OS
|
||||
/drivers/unix/ @godotengine/_platforms
|
||||
/drivers/windows/ @godotengine/windows
|
||||
/drivers/unix/ @godotengine/_platforms
|
||||
/drivers/windows/ @godotengine/windows
|
||||
|
||||
## Misc
|
||||
/drivers/png/ @godotengine/import
|
||||
/drivers/png/ @godotengine/import
|
||||
|
||||
# Editor
|
||||
|
||||
/editor/*debugger* @godotengine/debugger
|
||||
/editor/gui/ @godotengine/usability @godotengine/gui-nodes
|
||||
/editor/icons/ @godotengine/usability
|
||||
/editor/import/ @godotengine/import
|
||||
/editor/plugins/*2d_*.* @godotengine/2d-editor
|
||||
/editor/plugins/*3d_*.* @godotengine/3d-editor
|
||||
/editor/plugins/script_*.* @godotengine/script-editor
|
||||
/editor/plugins/*shader*.* @godotengine/shaders
|
||||
/editor/themes/ @godotengine/usability @godotengine/gui-nodes
|
||||
/editor/code_editor.* @godotengine/script-editor
|
||||
/editor/*dock*.* @godotengine/docks
|
||||
/editor/*shader*.* @godotengine/shaders
|
||||
/editor/*debugger* @godotengine/debugger
|
||||
/editor/gui/ @godotengine/usability @godotengine/gui-nodes
|
||||
/editor/icons/ @godotengine/usability
|
||||
/editor/import/ @godotengine/import
|
||||
/editor/plugins/*2d_*.* @godotengine/2d-editor
|
||||
/editor/plugins/*3d_*.* @godotengine/3d-editor
|
||||
/editor/plugins/script_*.* @godotengine/script-editor
|
||||
/editor/plugins/*shader*.* @godotengine/shaders
|
||||
/editor/themes/ @godotengine/usability @godotengine/gui-nodes
|
||||
/editor/code_editor.* @godotengine/script-editor
|
||||
/editor/*dock*.* @godotengine/docks
|
||||
/editor/*shader*.* @godotengine/shaders
|
||||
|
||||
# Main
|
||||
|
||||
/main/ @godotengine/core
|
||||
/main/ @godotengine/core
|
||||
|
||||
# Misc
|
||||
|
||||
/misc/ @godotengine/buildsystem
|
||||
/misc/extension_api_validation/ @godotengine/gdextension @godotengine/dotnet
|
||||
/misc/ @godotengine/buildsystem
|
||||
/misc/extension_api_validation/ @godotengine/gdextension @godotengine/dotnet
|
||||
|
||||
# Modules
|
||||
|
||||
## Audio (+ video)
|
||||
/modules/minimp3/ @godotengine/audio
|
||||
/modules/ogg/ @godotengine/audio
|
||||
/modules/opus/ @godotengine/audio
|
||||
/modules/theora/ @godotengine/audio
|
||||
/modules/vorbis/ @godotengine/audio
|
||||
/modules/webm/ @godotengine/audio
|
||||
/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/ogg/doc_classes/ @godotengine/audio @godotengine/documentation
|
||||
/modules/theora/ @godotengine/audio
|
||||
/modules/theora/doc_classes/ @godotengine/audio @godotengine/documentation
|
||||
/modules/vorbis/ @godotengine/audio
|
||||
/modules/vorbis/doc_classes/ @godotengine/audio @godotengine/documentation
|
||||
|
||||
## Import
|
||||
/modules/basis_universal/ @godotengine/import
|
||||
/modules/bmp/ @godotengine/import
|
||||
/modules/cvtt/ @godotengine/import
|
||||
/modules/dds/ @godotengine/import
|
||||
/modules/etc/ @godotengine/import
|
||||
/modules/fbx/ @godotengine/import
|
||||
/modules/gltf/ @godotengine/import
|
||||
/modules/hdr/ @godotengine/import
|
||||
/modules/jpg/ @godotengine/import
|
||||
/modules/pvr/ @godotengine/import
|
||||
/modules/squish/ @godotengine/import
|
||||
/modules/svg/ @godotengine/import
|
||||
/modules/tga/ @godotengine/import
|
||||
/modules/tinyexr/ @godotengine/import
|
||||
/modules/webp/ @godotengine/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/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/ktx/ @godotengine/import
|
||||
/modules/squish/ @godotengine/import
|
||||
/modules/svg/ @godotengine/import
|
||||
/modules/tga/ @godotengine/import
|
||||
/modules/tinyexr/ @godotengine/import
|
||||
/modules/webp/ @godotengine/import
|
||||
|
||||
## Network
|
||||
/modules/enet/ @godotengine/network
|
||||
/modules/mbedtls/ @godotengine/network
|
||||
/modules/upnp/ @godotengine/network
|
||||
/modules/webrtc/ @godotengine/network
|
||||
/modules/websocket/ @godotengine/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/vhacd/ @godotengine/rendering
|
||||
/modules/xatlas_unwrap/ @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/mono/ @godotengine/dotnet
|
||||
/modules/gdscript/ @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/text_server_adv/ @godotengine/gui-nodes
|
||||
/modules/text_server_fb/ @godotengine/gui-nodes
|
||||
/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/webxr/ @godotengine/xr
|
||||
/modules/camera/ @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/gridmap/ @godotengine/3d-nodes
|
||||
/modules/opensimplex/ @godotengine/3d-nodes
|
||||
/modules/regex/ @godotengine/core
|
||||
/modules/csg/ @godotengine/3d-nodes
|
||||
/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/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/ios/ @godotengine/ios
|
||||
/platform/linuxbsd/ @godotengine/linux-bsd
|
||||
/platform/macos/ @godotengine/macos
|
||||
/platform/web/ @godotengine/web
|
||||
/platform/windows/ @godotengine/windows
|
||||
/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/3d/ @godotengine/3d-nodes
|
||||
/scene/animation/ @godotengine/animation
|
||||
/scene/audio/ @godotengine/audio
|
||||
/scene/debugger/ @godotengine/debugger
|
||||
/scene/gui/ @godotengine/gui-nodes
|
||||
/scene/main/ @godotengine/core
|
||||
/scene/resources/font.* @godotengine/gui-nodes
|
||||
/scene/resources/text_line.* @godotengine/gui-nodes
|
||||
/scene/resources/text_paragraph.* @godotengine/gui-nodes
|
||||
/scene/resources/visual_shader*.* @godotengine/shaders
|
||||
/scene/theme/ @godotengine/gui-nodes
|
||||
/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
|
||||
/scene/gui/ @godotengine/gui-nodes
|
||||
/scene/main/ @godotengine/core
|
||||
/scene/resources/font.* @godotengine/gui-nodes
|
||||
/scene/resources/text_line.* @godotengine/gui-nodes
|
||||
/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
|
||||
|
||||
/servers/audio* @godotengine/audio
|
||||
/servers/camera* @godotengine/xr
|
||||
/servers/display_server.* @godotengine/_platforms
|
||||
/servers/navigation_server*.* @godotengine/navigation
|
||||
/servers/physics* @godotengine/physics
|
||||
/servers/rendering* @godotengine/rendering
|
||||
/servers/text_server.* @godotengine/gui-nodes
|
||||
/servers/xr* @godotengine/xr
|
||||
/servers/audio* @godotengine/audio
|
||||
/servers/camera* @godotengine/xr
|
||||
/servers/display_server.* @godotengine/_platforms
|
||||
/servers/navigation_server*.* @godotengine/navigation
|
||||
/servers/physics* @godotengine/physics
|
||||
/servers/rendering* @godotengine/rendering
|
||||
/servers/text_server.* @godotengine/gui-nodes
|
||||
/servers/xr* @godotengine/xr
|
||||
|
||||
# Tests
|
||||
|
||||
/tests/ @godotengine/tests
|
||||
/tests/ @godotengine/tests
|
||||
|
||||
# Thirdparty
|
||||
|
||||
/thirdparty/ @godotengine/buildsystem
|
||||
/thirdparty/ @godotengine/buildsystem
|
||||
|
||||
# Buildsystem (After everything to catch all)
|
||||
|
||||
*.py @godotengine/buildsystem
|
||||
SConstruct @godotengine/buildsystem
|
||||
SCsub @godotengine/buildsystem
|
||||
|
|
|
@ -1,72 +1,72 @@
|
|||
name: Bug report
|
||||
description: Report a bug in Godot
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
When reporting bugs, please follow the guidelines in this template. This helps identify the problem precisely and thus enables contributors to fix it faster.
|
||||
- Write a descriptive issue title above.
|
||||
- The golden rule is to **always open *one* issue for *one* bug**. If you notice several bugs and want to report them, make sure to create one new issue for each of them.
|
||||
- Search [open](https://github.com/godotengine/godot/issues) and [closed](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported. If you don't find a relevant match or if you're unsure, don't hesitate to **open a new issue**. The bugsquad will handle it from there if it's a duplicate.
|
||||
- Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/latest/about/release_policy.html). Please always check if your issue is reproducible in the latest version – it may already have been fixed!
|
||||
- If you use a custom build, please test if your issue is reproducible in official builds too. Likewise if you use any C++ modules, GDExtensions, or editor plugins, you should check if the bug is reproducible in a project without these.
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
When reporting bugs, please follow the guidelines in this template. This helps identify the problem precisely and thus enables contributors to fix it faster.
|
||||
- Write a descriptive issue title above.
|
||||
- The golden rule is to **always open *one* issue for *one* bug**. If you notice several bugs and want to report them, make sure to create one new issue for each of them.
|
||||
- Search [open](https://github.com/godotengine/godot/issues) and [closed](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported. If you don't find a relevant match or if you're unsure, don't hesitate to **open a new issue**. The bugsquad will handle it from there if it's a duplicate.
|
||||
- Verify that you are using a [supported Godot version](https://docs.godotengine.org/en/latest/about/release_policy.html). Please always check if your issue is reproducible in the latest version – it may already have been fixed!
|
||||
- If you use a custom build, please test if your issue is reproducible in official builds too. Likewise if you use any C++ modules, GDExtensions, or editor plugins, you should check if the bug is reproducible in a project without these.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Tested versions
|
||||
description: |
|
||||
To properly fix a bug, we need to identify if the bug was recently introduced in the engine, or if it was always present.
|
||||
- Please specify the Godot version you found the issue in, including the **Git commit hash** if using a development or non-official build. The exact Godot version (including the commit hash) can be copied by clicking the version shown in the editor (bottom bar) or in the project manager (top bar).
|
||||
- If you can, **please test earlier Godot versions** (previous stable branch, and development snapshots of the current feature release) and, if applicable, newer versions (development snapshots for the next feature release). Mention whether the bug is reproducible or not in the versions you tested. You can find all Godot releases in our [download archive](https://godotengine.org/download/archive/).
|
||||
- The aim is for us to identify whether a bug is a **regression**, i.e. an issue that didn't exist in a previous version, but was introduced later on, breaking existing functionality. For example, if a bug is reproducible in 4.2.stable but not in 4.1.stable, we would like you to test intermediate 4.2 dev and beta snapshots to find which snapshot is the first one where the issue can be reproduced.
|
||||
placeholder: |
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Tested versions
|
||||
description: |
|
||||
To properly fix a bug, we need to identify if the bug was recently introduced in the engine, or if it was always present.
|
||||
- Please specify the Godot version you found the issue in, including the **Git commit hash** if using a development or non-official build. The exact Godot version (including the commit hash) can be copied by clicking the version shown in the editor (bottom bar) or in the project manager (top bar).
|
||||
- If you can, **please test earlier Godot versions** (previous stable branch, and development snapshots of the current feature release) and, if applicable, newer versions (development snapshots for the next feature release). Mention whether the bug is reproducible or not in the versions you tested. You can find all Godot releases in our [download archive](https://godotengine.org/download/archive/).
|
||||
- The aim is for us to identify whether a bug is a **regression**, i.e. an issue that didn't exist in a previous version, but was introduced later on, breaking existing functionality. For example, if a bug is reproducible in 4.2.stable but not in 4.1.stable, we would like you to test intermediate 4.2 dev and beta snapshots to find which snapshot is the first one where the issue can be reproduced.
|
||||
placeholder: |
|
||||
- Reproducible in: 4.3.dev [d76c1d0e5], 4.2.stable, 4.2.dev5 and later 4.2 snapshots.
|
||||
- Not reproducible in: 4.1.3.stable, 4.2.dev4 and earlier 4.2 snapshots.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- Reproducible in: 4.3.dev [d76c1d0e5], 4.2.stable, 4.2.dev5 and later 4.2 snapshots.
|
||||
- Not reproducible in: 4.1.3.stable, 4.2.dev4 and earlier 4.2 snapshots.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: System information
|
||||
description: |
|
||||
- Specify the OS version, and when relevant hardware information.
|
||||
- For issues that are likely OS-specific and/or graphics-related, please specify the CPU model and architecture.
|
||||
- For graphics-related issues, specify the GPU model, driver version, and the rendering backend (GLES2, GLES3, Vulkan).
|
||||
- **Bug reports not including the required information may be closed at the maintainers' discretion.** If in doubt, always include all the requested information; it's better to include too much information than not enough information.
|
||||
- **Starting from Godot 4.1, you can copy this information to your clipboard by using *Help > Copy System Info* at the top of the editor window.**
|
||||
placeholder: Windows 10 - Godot v4.0.3.stable - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 970 (nvidia, 510.85.02) - Intel Core i7-10700KF CPU @ 3.80GHz (16 Threads)
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: System information
|
||||
description: |
|
||||
- Specify the OS version, and when relevant hardware information.
|
||||
- For issues that are likely OS-specific and/or graphics-related, please specify the CPU model and architecture.
|
||||
- For graphics-related issues, specify the GPU model, driver version, and the rendering backend (GLES2, GLES3, Vulkan).
|
||||
- **Bug reports not including the required information may be closed at the maintainers' discretion.** If in doubt, always include all the requested information; it's better to include too much information than not enough information.
|
||||
- **Starting from Godot 4.1, you can copy this information to your clipboard by using *Help > Copy System Info* at the top of the editor window.**
|
||||
placeholder: Windows 10 - Godot v4.0.3.stable - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 970 (nvidia, 510.85.02) - Intel Core i7-10700KF CPU @ 3.80GHz (16 Threads)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Issue description
|
||||
description: |
|
||||
Describe your issue briefly. What doesn't work, and how do you expect it to work instead?
|
||||
You can include images or videos with drag and drop, and format code blocks or logs with <code>\`\`\`</code> tags, on separate lines before and after the text. (Use <code>\`\`\`gdscript</code> to add GDScript syntax highlighting.)
|
||||
Please do not add code examples or error messages as screenshots, but as text, this helps searching for issues and testing the code. If you are reporting a bug in the editor interface, like the script editor, please provide both a screenshot *and* the text of the code to help with testing.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Issue description
|
||||
description: |
|
||||
Describe your issue briefly. What doesn't work, and how do you expect it to work instead?
|
||||
You can include images or videos with drag and drop, and format code blocks or logs with <code>\`\`\`</code> tags, on separate lines before and after the text. (Use <code>\`\`\`gdscript</code> to add GDScript syntax highlighting.)
|
||||
Please do not add code examples or error messages as screenshots, but as text, this helps searching for issues and testing the code. If you are reporting a bug in the editor interface, like the script editor, please provide both a screenshot *and* the text of the code to help with testing.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: |
|
||||
List of steps or sample code that reproduces the issue. Having reproducible issues is a prerequisite for contributors to be able to solve them.
|
||||
If you include a minimal reproduction project below, you can detail how to use it here.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: |
|
||||
List of steps or sample code that reproduces the issue. Having reproducible issues is a prerequisite for contributors to be able to solve them.
|
||||
If you include a minimal reproduction project below, you can detail how to use it here.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Minimal reproduction project (MRP)
|
||||
description: |
|
||||
- A small Godot project which reproduces the issue, with no unnecessary files included. Be sure to not include the `.godot` folder in the archive (but keep `project.godot`).
|
||||
- Having an MRP is very important for contributors to be able to reproduce the bug in the same way that you are experiencing it. When testing a potential fix for the issue, contributors will use the MRP to validate that the fix is working as intended.
|
||||
- If the reproduction steps are not project dependent (e.g. the bug is visible in a brand new project), you can write "N/A" in the field.
|
||||
- Drag and drop a ZIP archive to upload it (max 10 MB). **Do not select another field until the project is done uploading.**
|
||||
- **Note for C# users:** If your issue is *not* C#-specific, please upload a minimal reproduction project written in GDScript. This will make it easier for contributors to reproduce the issue locally as not everyone has a .NET setup available.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Minimal reproduction project (MRP)
|
||||
description: |
|
||||
- A small Godot project which reproduces the issue, with no unnecessary files included. Be sure to not include the `.godot` folder in the archive (but keep `project.godot`).
|
||||
- Having an MRP is very important for contributors to be able to reproduce the bug in the same way that you are experiencing it. When testing a potential fix for the issue, contributors will use the MRP to validate that the fix is working as intended.
|
||||
- If the reproduction steps are not project dependent (e.g. the bug is visible in a brand new project), you can write "N/A" in the field.
|
||||
- Drag and drop a ZIP archive to upload it (max 10 MB). **Do not select another field until the project is done uploading.**
|
||||
- **Note for C# users:** If your issue is *not* C#-specific, please upload a minimal reproduction project written in GDScript. This will make it easier for contributors to reproduce the issue locally as not everyone has a .NET setup available.
|
||||
validations:
|
||||
required: true
|
||||
|
|
|
@ -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,25 +14,26 @@ 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 }}
|
||||
SCONS_CACHE: ${{ inputs.scons-cache }}
|
||||
SCONS_CACHE_LIMIT: ${{ inputs.scons-cache-limit }}
|
||||
SCONSFLAGS: ${{ inputs.sconsflags }}
|
||||
SCONS_CACHE: ${{ inputs.scons-cache }}
|
||||
SCONS_CACHE_LIMIT: ${{ inputs.scons-cache-limit }}
|
||||
run: |
|
||||
echo "Building with flags:" platform=${{ inputs.platform }} target=${{ inputs.target }} tests=${{ inputs.tests }} ${{ env.SCONSFLAGS }}
|
||||
|
||||
|
|
|
@ -3,18 +3,19 @@ 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
|
||||
with:
|
||||
path: ${{inputs.scons-cache}}
|
||||
key: ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
|
||||
path: ${{ inputs.scons-cache }}
|
||||
key: ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}
|
||||
|
||||
# We try to match an existing cache to restore from it. Each potential key is checked against
|
||||
# all existing caches as a prefix. E.g. 'linux-template-minimal' would match any cache that
|
||||
|
@ -28,7 +29,7 @@ runs:
|
|||
# 4. A partial match for the same base branch only (not ideal, matches any PR with the same base branch).
|
||||
|
||||
restore-keys: |
|
||||
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
|
||||
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}
|
||||
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-refs/heads/${{env.GODOT_BASE_BRANCH}}
|
||||
${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}
|
||||
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}
|
||||
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}
|
||||
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-refs/heads/${{ env.GODOT_BASE_BRANCH }}
|
||||
${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}
|
||||
|
|
|
@ -3,15 +3,16 @@ 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
|
||||
with:
|
||||
path: ${{inputs.scons-cache}}
|
||||
key: ${{inputs.cache-name}}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
|
||||
path: ${{ inputs.scons-cache }}
|
||||
key: ${{ inputs.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -9,12 +9,12 @@ env:
|
|||
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no module_text_server_fb_enabled=yes strict_checks=yes
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-android
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-android
|
||||
cancel-in-progress: true
|
||||
|
||||
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,62 +7,58 @@ 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
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-cpp-tests
|
||||
cancel-in-progress: true
|
||||
|
||||
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
|
||||
|
|
|
@ -9,16 +9,17 @@ env:
|
|||
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no module_text_server_fb_enabled=yes strict_checks=yes
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-ios
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-ios
|
||||
cancel-in-progress: true
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -12,12 +12,12 @@ env:
|
|||
TSAN_OPTIONS: suppressions=misc/error_suppressions/tsan.txt
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-linux
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-linux
|
||||
cancel-in-progress: true
|
||||
|
||||
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 }}
|
||||
|
|
|
@ -9,12 +9,12 @@ env:
|
|||
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes strict_checks=yes
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-macos
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-macos
|
||||
cancel-in-progress: true
|
||||
|
||||
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,52 +1,46 @@
|
|||
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
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-runner
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
# First stage: Only static checks, fast and prevent expensive builds from running.
|
||||
|
||||
static-checks:
|
||||
if: ${{ vars.DISABLE_GODOT_CI == '' }}
|
||||
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
|
||||
|
|
|
@ -3,7 +3,7 @@ on:
|
|||
workflow_call:
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-static
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-static
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
|
@ -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,15 +8,15 @@ 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
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-web
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
web-template:
|
||||
runs-on: "ubuntu-22.04"
|
||||
runs-on: ubuntu-22.04
|
||||
name: ${{ matrix.name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -37,16 +37,17 @@ jobs:
|
|||
artifact: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Emscripten latest
|
||||
uses: mymindstorm/setup-emsdk@v14
|
||||
with:
|
||||
version: ${{env.EM_VERSION}}
|
||||
actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
|
||||
cache-key: emsdk-${{ matrix.cache-name }}-${{env.GODOT_BASE_BRANCH}}-${{github.ref}}-${{github.sha}}
|
||||
version: ${{ env.EM_VERSION }}
|
||||
actions-cache-folder: ${{ env.EM_CACHE_FOLDER }}
|
||||
cache-key: emsdk-${{ matrix.cache-name }}-${{ env.GODOT_BASE_BRANCH }}-${{ github.ref }}-${{ github.sha }}
|
||||
|
||||
- name: Verify Emscripten setup
|
||||
run: |
|
||||
|
@ -77,6 +78,6 @@ jobs:
|
|||
|
||||
- name: Upload artifact
|
||||
uses: ./.github/actions/upload-artifact
|
||||
if: ${{ matrix.artifact }}
|
||||
if: matrix.artifact
|
||||
with:
|
||||
name: ${{ matrix.cache-name }}
|
||||
|
|
|
@ -7,17 +7,17 @@ on:
|
|||
env:
|
||||
# Used for the cache key. Add version suffix to force clean build.
|
||||
GODOT_BASE_BRANCH: master
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes d3d12=yes strict_checks=yes "angle_libs=${{github.workspace}}/"
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes d3d12=yes strict_checks=yes "angle_libs=${{ github.workspace }}/"
|
||||
SCONS_CACHE_MSVC_CONFIG: true
|
||||
|
||||
concurrency:
|
||||
group: ci-${{github.actor}}-${{github.head_ref || github.run_number}}-${{github.ref}}-windows
|
||||
group: ci-${{ github.actor }}-${{ github.head_ref || github.run_number }}-${{ github.ref }}-windows
|
||||
cancel-in-progress: true
|
||||
|
||||
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
|
||||
|
||||
|
@ -73,7 +74,7 @@ jobs:
|
|||
target: angle/angle.zip
|
||||
|
||||
- name: Extract pre-built ANGLE static libraries
|
||||
run: Expand-Archive -Force angle/angle.zip ${{github.workspace}}/
|
||||
run: Expand-Archive -Force angle/angle.zip ${{ github.workspace }}/
|
||||
|
||||
- name: Setup MSVC problem matcher
|
||||
uses: ammaraskar/msvc-problem-matcher@master
|
||||
|
@ -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
|
||||
|
|
77
DONORS.md
77
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/>
|
||||
Load Complete <https://loadcomplete.com/>
|
||||
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
|
||||
|
||||
|
|
74
SConstruct
74
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:
|
||||
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 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.");
|
||||
call_with_variant_args_ret(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||
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.");
|
||||
call_with_variant_args_retc(data.instance, data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||
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 {
|
||||
call_with_variant_args_static_ret(data.method, p_arguments, p_argcount, r_return_value, r_call_error);
|
||||
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.");\\
|
||||
$RVOID\\
|
||||
}\\
|
||||
$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,28 +491,26 @@ 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (singleton->task_queue.first()) {
|
||||
task_to_process = task_queue.first()->self();
|
||||
task_queue.remove(task_queue.first());
|
||||
}
|
||||
if (singleton->task_queue.first()) {
|
||||
task_to_process = task_queue.first()->self();
|
||||
task_queue.remove(task_queue.first());
|
||||
}
|
||||
|
||||
if (!task_to_process) {
|
||||
p_caller_pool_thread->awaited_task = p_task;
|
||||
if (!task_to_process) {
|
||||
p_caller_pool_thread->awaited_task = p_task;
|
||||
|
||||
_unlock_unlockable_mutexes();
|
||||
relock_unlockables = true;
|
||||
p_caller_pool_thread->cond_var.wait(lock);
|
||||
_unlock_unlockable_mutexes();
|
||||
relock_unlockables = true;
|
||||
|
||||
DEV_ASSERT(exit_threads || p_caller_pool_thread->signaled || IS_WAIT_OVER);
|
||||
p_caller_pool_thread->awaited_task = nullptr;
|
||||
}
|
||||
p_caller_pool_thread->cond_var.wait(lock);
|
||||
|
||||
p_caller_pool_thread->awaited_task = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
// 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.
|
||||
ScriptServer::thread_enter();
|
||||
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;
|
||||
}
|
||||
|
||||
String TranslationServer::get_fallback_locale() const {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return locales;
|
||||
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