Compare commits
196 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6699ae7897 | ||
|
53cde2eb85 | ||
|
6225d39826 | ||
|
3a2804a7e7 | ||
|
7b32e96f3d | ||
|
15129c044e | ||
|
56a1d07421 | ||
|
2c612abdd1 | ||
|
f273c7c773 | ||
|
99a8821a71 | ||
|
7a7e4129bd | ||
|
4abc358952 | ||
|
f7ad4dca8c | ||
|
35b4a1f374 | ||
|
4944d59198 | ||
|
0a83f06608 | ||
|
03168cc9d1 | ||
|
47f34e8436 | ||
|
abe68d397e | ||
|
7246e1488e | ||
|
a2e3c13451 | ||
|
3030d4b806 | ||
|
018f8be3d5 | ||
|
d92f9017c6 | ||
|
34251cf5b3 | ||
|
d00e4fbb16 | ||
|
927d7a9250 | ||
|
13701384ab | ||
|
f4b71b5325 | ||
|
51c86eb085 | ||
|
4addddd8df | ||
|
6dd8e7fece | ||
|
69713dadf0 | ||
|
90f1c3e7bd | ||
|
d51be1f68d | ||
|
3fac9e43af | ||
|
1d790deedb | ||
|
88370e44d8 | ||
|
c7a173aa60 | ||
|
e7e723b3e3 | ||
|
281642831c | ||
|
6b7f36e2a9 | ||
|
f757cc9a70 | ||
|
cab91cf8fb | ||
|
0b815cbb99 | ||
|
f11f9e3b7f | ||
|
b2b882cc1d | ||
|
f5b5b6cbfe | ||
|
02c45088ea | ||
|
7f0cc1aa35 | ||
|
21a0a84c6f | ||
|
fb1758ce23 | ||
|
c4525f24e3 | ||
|
61b2ad9242 | ||
|
d7a8654edd | ||
|
1629e9b1fa | ||
|
3783527410 | ||
|
00866dc80a | ||
|
d842870331 | ||
|
2635ff777e | ||
|
cbcc5f8d19 | ||
|
64cbde426f | ||
|
b1c1c40250 | ||
|
e09cada53f | ||
|
2b05cf154a | ||
|
26cc13705a | ||
|
af8caffd0e | ||
|
ec20c3ff76 | ||
|
a2f64b3c10 | ||
|
fc5e7c7411 | ||
|
1e5d7a0907 | ||
|
4d0f10a543 | ||
|
f8c9ec3f37 | ||
|
fd17fae4bd | ||
|
b1fda8f5c4 | ||
|
1250b4568a | ||
|
430a69baed | ||
|
b60bf28a2f | ||
|
5567fedd04 | ||
|
1a5ac1fd59 | ||
|
e72e42fe9b | ||
|
f783cf7b81 | ||
|
f3848b75cb | ||
|
19843328d9 | ||
|
1e9f578740 | ||
|
0a1724f713 | ||
|
e79157af72 | ||
|
6ab9ec33f2 | ||
|
4acc73dbfa | ||
|
e549ab35fa | ||
|
43fa723659 | ||
|
1c9ba616d5 | ||
|
682ee73f64 | ||
|
9946eba398 | ||
|
30bba8745c | ||
|
c4351c8d98 | ||
|
e2184c5da0 | ||
|
4fabc1ba58 | ||
|
4d7feff723 | ||
|
1d775b5b97 | ||
|
b6055941b9 | ||
|
e5be133032 | ||
|
0f33a4b97e | ||
|
f9bcd4f0ca | ||
|
169b568e65 | ||
|
95a0525361 | ||
|
8e1d1a54fe | ||
|
99dde70ad3 | ||
|
e59f59a439 | ||
|
afc330e33f | ||
|
219ddde30c | ||
|
2dd696867f | ||
|
9cf21b4b03 | ||
|
497570b1cf | ||
|
70a8761deb | ||
|
19bed8fee7 | ||
|
7874dad279 | ||
|
05860062a5 | ||
|
8496e0738f | ||
|
20ce427a6c | ||
|
40dcdcbe79 | ||
|
b2c83b42f6 | ||
|
cf40a5bc5a | ||
|
1ecf20c783 | ||
|
b05470efd0 | ||
|
433509b489 | ||
|
139f5ee15e | ||
|
bd552ff609 | ||
|
ecbb9a9c6a | ||
|
d0c4f19dd2 | ||
|
df6bbb2538 | ||
|
1d0bcae019 | ||
|
df522db6f0 | ||
|
c684d65c64 | ||
|
5676d398e0 | ||
|
32f2b851ab | ||
|
bf5907b724 | ||
|
cff0ebd603 | ||
|
9af6e04a15 | ||
|
39fb871310 | ||
|
eaa8ecb182 | ||
|
c7dbcbd6d4 | ||
|
f0f69a7b7c | ||
|
4168220169 | ||
|
d8c13f88ed | ||
|
7266418bdf | ||
|
b7fc063038 | ||
|
6c202154a7 | ||
|
6d41487459 | ||
|
3876287162 | ||
|
8ea64814ed | ||
|
6b323241b1 | ||
|
2d7266e764 | ||
|
7726ced085 | ||
|
bba8f85945 | ||
|
63ff665fd0 | ||
|
6e78eec37f | ||
|
6eea970e8c | ||
|
6aff947ee5 | ||
|
686591b948 | ||
|
acba31b746 | ||
|
d915947f3d | ||
|
a031407e82 | ||
|
26b151a945 | ||
|
2eb2052cb9 | ||
|
1f92092b08 | ||
|
c831bdbbe2 | ||
|
ea5989e3f5 | ||
|
6073b86e71 | ||
|
b84dbab84d | ||
|
1ebf488a4e | ||
|
4a64c95732 | ||
|
2b4ade1ed6 | ||
|
562e583872 | ||
|
cfa33666c9 | ||
|
3dc376ec0b | ||
|
a7d79f9e6c | ||
|
fac12603ef | ||
|
8c5edcb03a | ||
|
79848620ce | ||
|
91ed3cd307 | ||
|
302af188a1 | ||
|
2eec361f5f | ||
|
a70df8537e | ||
|
cbee16418a | ||
|
5a33e45fed | ||
|
6595395b8b | ||
|
a7756d530e | ||
|
2df506ea15 | ||
|
13d5227911 | ||
|
b9271608df | ||
|
5caaa6ce19 | ||
|
e1af61467a | ||
|
d40fc50f08 | ||
|
620cc30f2a | ||
|
ff9bc04223 |
235
.clang-format
235
.clang-format
@ -1,59 +1,29 @@
|
||||
# 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 18.1.8).
|
||||
BasedOnStyle: LLVM
|
||||
# chosen value in case the base style changes (last sync: Clang 14.0).
|
||||
---
|
||||
### General config, applies to all languages ###
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
# AlignArrayOfStructures: None
|
||||
# AlignConsecutiveAssignments:
|
||||
# Enabled: false
|
||||
# AcrossEmptyLines: false
|
||||
# AcrossComments: false
|
||||
# AlignCompound: false
|
||||
# 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
|
||||
# AlignConsecutiveMacros: None
|
||||
# AlignConsecutiveAssignments: None
|
||||
# AlignConsecutiveBitFields: None
|
||||
# AlignConsecutiveDeclarations: None
|
||||
# AlignEscapedNewlines: Right
|
||||
AlignOperands: DontAlign
|
||||
AlignTrailingComments:
|
||||
Kind: Never
|
||||
OverEmptyLines: 0
|
||||
AlignOperands: DontAlign
|
||||
AlignTrailingComments: false
|
||||
# AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
# AllowBreakBeforeNoexceptSpecifier: Never
|
||||
# AllowShortEnumsOnASingleLine: true
|
||||
# AllowShortBlocksOnASingleLine: Never
|
||||
# AllowShortCaseLabelsOnASingleLine: false
|
||||
# AllowShortCompoundRequirementOnASingleLine: true
|
||||
# AllowShortEnumsOnASingleLine: true
|
||||
# AllowShortFunctionsOnASingleLine: All
|
||||
# AllowShortIfStatementsOnASingleLine: Never
|
||||
# AllowShortLambdasOnASingleLine: All
|
||||
# AllowShortIfStatementsOnASingleLine: Never
|
||||
# AllowShortLoopsOnASingleLine: false
|
||||
# AlwaysBreakAfterDefinitionReturnType: None
|
||||
# AlwaysBreakAfterReturnType: None
|
||||
# AlwaysBreakBeforeMultilineStrings: false
|
||||
# AlwaysBreakTemplateDeclarations: MultiLine
|
||||
@ -61,49 +31,50 @@ 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
|
||||
# BreakBeforeConceptDeclarations: Always
|
||||
# BreakBeforeInlineASMColon: OnlyMultiline
|
||||
# BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: AfterColon
|
||||
# BreakBeforeInheritanceComma: false
|
||||
# BreakInheritanceList: BeforeColon
|
||||
# BreakBeforeTernaryOperators: true
|
||||
# BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: AfterColon
|
||||
# BreakStringLiterals: true
|
||||
ColumnLimit: 0
|
||||
# CommentPragmas: '^ IWYU pragma:'
|
||||
ColumnLimit: 0
|
||||
# CommentPragmas: '^ IWYU pragma:'
|
||||
# QualifierAlignment: Leave
|
||||
# CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
# DeriveLineEnding: true
|
||||
# DerivePointerAlignment: false
|
||||
# DisableFormat: false
|
||||
# DisableFormat: false
|
||||
# EmptyLineAfterAccessModifier: Never
|
||||
# EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
# ExperimentalAutoDetectBinPacking: false
|
||||
# PackConstructorInitializers: BinPack
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
# AllowAllConstructorInitializersOnNextLine: true
|
||||
# FixNamespaceComments: true
|
||||
# ForEachMacros:
|
||||
# - foreach
|
||||
@ -111,138 +82,118 @@ Cpp11BracedListStyle: false
|
||||
# - BOOST_FOREACH
|
||||
# IfMacros:
|
||||
# - KJ_IF_MAYBE
|
||||
# IncludeBlocks: Preserve
|
||||
# IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: ^".*"$
|
||||
Priority: 1
|
||||
- Regex: ^<.*\.h>$
|
||||
Priority: 2
|
||||
- Regex: ^<.*>$
|
||||
Priority: 3
|
||||
# IncludeIsMainRegex: (Test)?$
|
||||
- Regex: '".*"'
|
||||
Priority: 1
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 2
|
||||
- Regex: '^<.*'
|
||||
Priority: 3
|
||||
# IncludeIsMainRegex: '(Test)?$'
|
||||
# IncludeIsMainSourceRegex: ''
|
||||
# IndentAccessModifiers: false
|
||||
# IndentCaseBlocks: false
|
||||
IndentCaseLabels: true
|
||||
# IndentExternBlock: AfterExternBlock
|
||||
# IndentCaseBlocks: false
|
||||
# IndentGotoLabels: true
|
||||
# IndentPPDirectives: None
|
||||
# IndentRequiresClause: true
|
||||
IndentWidth: 4
|
||||
# IndentExternBlock: AfterExternBlock
|
||||
# IndentRequires: false
|
||||
IndentWidth: 4
|
||||
# IndentWrappedFunctionNames: false
|
||||
# InsertBraces: 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
|
||||
# ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 4
|
||||
# ObjCBreakBeforeNestedBlockParam: true
|
||||
# ObjCSpaceAfterProperty: false
|
||||
# ObjCSpaceBeforeProtocolList: true
|
||||
# PPIndentWidth: -1
|
||||
PackConstructorInitializers: NextLine
|
||||
# PenaltyBreakAssignment: 2
|
||||
# PenaltyBreakBeforeFirstCallParameter: 19
|
||||
# PenaltyBreakComment: 300
|
||||
# PenaltyBreakFirstLessLess: 120
|
||||
# PenaltyBreakOpenParenthesis: 0
|
||||
# PenaltyBreakScopeResolution: 500
|
||||
# PenaltyBreakString: 1000
|
||||
# PenaltyBreakTemplateDeclaration: 10
|
||||
# PenaltyExcessCharacter: 1000000
|
||||
# PenaltyIndentedWhitespace: 0
|
||||
# PenaltyReturnTypeOnItsOwnLine: 60
|
||||
# PenaltyIndentedWhitespace: 0
|
||||
# PointerAlignment: Right
|
||||
# QualifierAlignment: Leave
|
||||
# PPIndentWidth: -1
|
||||
# ReferenceAlignment: Pointer
|
||||
# ReflowComments: true
|
||||
# ReflowComments: true
|
||||
# RemoveBracesLLVM: false
|
||||
# RemoveParentheses: Leave
|
||||
# RemoveSemicolon: false
|
||||
# RequiresClausePosition: OwnLine
|
||||
# RequiresExpressionIndentation: OuterScope
|
||||
# SeparateDefinitionBlocks: Leave
|
||||
# ShortNamespaceLines: 1
|
||||
# SkipMacroDefinitionBody: false
|
||||
# SortIncludes: CaseSensitive
|
||||
# SortIncludes: CaseSensitive
|
||||
# SortJavaStaticImport: Before
|
||||
# SortUsingDeclarations: LexicographicNumeric
|
||||
# SortUsingDeclarations: true
|
||||
# SpaceAfterCStyleCast: false
|
||||
# SpaceAfterLogicalNot: false
|
||||
# SpaceAfterTemplateKeyword: true
|
||||
# SpaceAroundPointerQualifiers: Default
|
||||
# SpaceBeforeAssignmentOperators: true
|
||||
# SpaceBeforeCaseColon: false
|
||||
# SpaceBeforeCpp11BracedList: false
|
||||
# SpaceBeforeCtorInitializerColon: true
|
||||
# SpaceBeforeInheritanceColon: true
|
||||
# SpaceBeforeJsonColon: false
|
||||
# SpaceBeforeParens: ControlStatements
|
||||
# SpaceBeforeParensOptions:
|
||||
# AfterControlStatements: true
|
||||
# AfterForeachMacros: true
|
||||
# AfterFunctionDeclarationName: false
|
||||
# AfterFunctionDefinitionName: false
|
||||
# AfterIfMacros: true
|
||||
# AfterFunctionDeclarationName: false
|
||||
# AfterIfMacros: true
|
||||
# AfterOverloadedOperator: false
|
||||
# AfterPlacementOperator: true
|
||||
# AfterRequiresInClause: false
|
||||
# AfterRequiresInExpression: false
|
||||
# BeforeNonEmptyParentheses: false
|
||||
# SpaceAroundPointerQualifiers: Default
|
||||
# SpaceBeforeRangeBasedForLoopColon: true
|
||||
# SpaceBeforeSquareBrackets: false
|
||||
# SpaceInEmptyBlock: false
|
||||
# SpaceInEmptyParentheses: false
|
||||
# SpacesBeforeTrailingComments: 1
|
||||
# SpacesInAngles: Never
|
||||
# SpacesInAngles: Never
|
||||
# SpacesInConditionalStatement: false
|
||||
# SpacesInContainerLiterals: true
|
||||
# SpacesInCStyleCastParentheses: false
|
||||
## Godot TODO: We'll want to use a min of 1, but we need to see how to fix
|
||||
## our comment capitalization at the same time.
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 0
|
||||
Maximum: -1
|
||||
# SpacesInParens: Never
|
||||
# SpacesInParensOptions:
|
||||
# InConditionalStatements: false
|
||||
# InCStyleCasts: false
|
||||
# InEmptyParentheses: false
|
||||
# Other: false
|
||||
Minimum: 0
|
||||
Maximum: -1
|
||||
# SpacesInParentheses: false
|
||||
# SpacesInSquareBrackets: false
|
||||
Standard: c++17
|
||||
# SpaceBeforeSquareBrackets: false
|
||||
# BitFieldColonSpacing: Both
|
||||
# StatementAttributeLikeMacros:
|
||||
# - Q_EMIT
|
||||
# StatementMacros:
|
||||
# - Q_UNUSED
|
||||
# - QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
UseTab: Always
|
||||
# VerilogBreakBetweenInstancePorts: true
|
||||
TabWidth: 4
|
||||
# UseCRLF: false
|
||||
UseTab: Always
|
||||
# WhitespaceSensitiveMacros:
|
||||
# - BOOST_PP_STRINGIZE
|
||||
# - CF_SWIFT_NAME
|
||||
# - NS_SWIFT_NAME
|
||||
# - PP_STRINGIZE
|
||||
# - STRINGIZE
|
||||
# - PP_STRINGIZE
|
||||
# - BOOST_PP_STRINGIZE
|
||||
# - NS_SWIFT_NAME
|
||||
# - CF_SWIFT_NAME
|
||||
---
|
||||
### C++ specific config ###
|
||||
Language: Cpp
|
||||
Standard: c++17
|
||||
---
|
||||
### ObjC specific config ###
|
||||
Language: ObjC
|
||||
# ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 4
|
||||
# ObjCBreakBeforeNestedBlockParam: true
|
||||
# ObjCSpaceAfterProperty: false
|
||||
# ObjCSpaceBeforeProtocolList: true
|
||||
---
|
||||
### Java specific config ###
|
||||
Language: Java
|
||||
# BreakAfterJavaFieldAnnotations: false
|
||||
JavaImportGroups: ['org.godotengine', 'android', 'androidx', 'com.android', 'com.google', 'java', 'javax']
|
||||
...
|
||||
|
@ -54,6 +54,3 @@ df61dc4b2bd54a5a40c515493c76f5a458e5b541
|
||||
|
||||
# Enforce template syntax `typename` over `class`
|
||||
9903e6779b70fc03aae70a37b9cf053f4f355b91
|
||||
|
||||
# Style: Apply new `clang-format` fixes
|
||||
b37fc1014abf7adda70dc30b0822d775b3a4433f
|
||||
|
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -1,6 +1,6 @@
|
||||
# Properly detect languages on Github
|
||||
*.h linguist-language=C++
|
||||
*.inc linguist-language=C++
|
||||
*.h linguist-language=cpp
|
||||
*.inc linguist-language=cpp
|
||||
thirdparty/* linguist-vendored
|
||||
|
||||
# Normalize EOL for all files that Git considers text files
|
||||
|
292
.github/CODEOWNERS
vendored
292
.github/CODEOWNERS
vendored
@ -4,234 +4,180 @@
|
||||
|
||||
# Buildsystem
|
||||
|
||||
* @godotengine/buildsystem
|
||||
.* @godotengine/buildsystem
|
||||
.github/ @godotengine/buildsystem
|
||||
*.py @godotengine/buildsystem
|
||||
SConstruct @godotengine/buildsystem
|
||||
SCsub @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/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
|
||||
/modules/minimp3/ @godotengine/audio
|
||||
/modules/ogg/ @godotengine/audio
|
||||
/modules/opus/ @godotengine/audio
|
||||
/modules/theora/ @godotengine/audio
|
||||
/modules/vorbis/ @godotengine/audio
|
||||
/modules/webm/ @godotengine/audio
|
||||
|
||||
## 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
|
||||
/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
|
||||
|
||||
## 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
|
||||
/modules/enet/ @godotengine/network
|
||||
/modules/mbedtls/ @godotengine/network
|
||||
/modules/upnp/ @godotengine/network
|
||||
/modules/webrtc/ @godotengine/network
|
||||
/modules/websocket/ @godotengine/network
|
||||
|
||||
## 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
|
||||
/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
|
||||
|
||||
## Scripting
|
||||
/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
|
||||
/modules/gdscript/ @godotengine/gdscript
|
||||
/modules/jsonrpc/ @godotengine/gdscript
|
||||
/modules/mono/ @godotengine/dotnet
|
||||
|
||||
## Text
|
||||
/modules/freetype/ @godotengine/buildsystem
|
||||
/modules/msdfgen/ @godotengine/buildsystem
|
||||
/modules/text_server_adv/ @godotengine/gui-nodes
|
||||
/modules/text_server_adv/doc_classes/ @godotengine/gui-nodes @godotengine/documentation
|
||||
/modules/text_server_fb/ @godotengine/gui-nodes
|
||||
/modules/text_server_fb/doc_classes/ @godotengine/gui-nodes @godotengine/documentation
|
||||
/modules/freetype/ @godotengine/buildsystem
|
||||
/modules/text_server_adv/ @godotengine/gui-nodes
|
||||
/modules/text_server_fb/ @godotengine/gui-nodes
|
||||
|
||||
## 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
|
||||
/modules/camera/ @godotengine/xr
|
||||
/modules/gdextension/xr/ @godotengine/xr
|
||||
/modules/mobile_vr/ @godotengine/xr
|
||||
/modules/webxr/ @godotengine/xr
|
||||
|
||||
## Misc
|
||||
/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
|
||||
/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
|
||||
|
||||
# Platform
|
||||
|
||||
/platform/android/ @godotengine/android
|
||||
/platform/android/doc_classes/ @godotengine/android @godotengine/documentation
|
||||
/platform/ios/ @godotengine/ios
|
||||
/platform/ios/doc_classes/ @godotengine/ios @godotengine/documentation
|
||||
/platform/linuxbsd/ @godotengine/linux-bsd
|
||||
/platform/linuxbsd/doc_classes/ @godotengine/linux-bsd @godotengine/documentation
|
||||
/platform/macos/ @godotengine/macos
|
||||
/platform/macos/doc_classes/ @godotengine/macos @godotengine/documentation
|
||||
/platform/web/ @godotengine/web
|
||||
/platform/web/doc_classes/ @godotengine/web @godotengine/documentation
|
||||
/platform/windows/ @godotengine/windows
|
||||
/platform/windows/doc_classes/ @godotengine/windows @godotengine/documentation
|
||||
/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
|
||||
|
||||
# Scene
|
||||
|
||||
/scene/2d/ @godotengine/2d-nodes
|
||||
/scene/2d/physics/ @godotengine/2d-nodes @godotengine/physics
|
||||
/scene/3d/ @godotengine/3d-nodes
|
||||
/scene/3d/physics/ @godotengine/3d-nodes @godotengine/physics
|
||||
/scene/animation/ @godotengine/animation
|
||||
/scene/audio/ @godotengine/audio
|
||||
/scene/debugger/ @godotengine/debugger
|
||||
/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
|
||||
/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
|
||||
|
||||
# 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
|
||||
|
||||
# Buildsystem (After everything to catch all)
|
||||
|
||||
*.py @godotengine/buildsystem
|
||||
SConstruct @godotengine/buildsystem
|
||||
SCsub @godotengine/buildsystem
|
||||
/thirdparty/ @godotengine/buildsystem
|
||||
|
126
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
126
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -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: 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: 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.
|
||||
|
||||
- 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: 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: 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
|
||||
- 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: 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: 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: 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: 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: 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: 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
|
||||
|
8
.github/actions/download-artifact/action.yml
vendored
8
.github/actions/download-artifact/action.yml
vendored
@ -1,17 +1,15 @@
|
||||
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
|
||||
|
8
.github/actions/godot-api-dump/action.yml
vendored
8
.github/actions/godot-api-dump/action.yml
vendored
@ -1,13 +1,11 @@
|
||||
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
|
||||
@ -21,5 +19,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/*'
|
||||
|
21
.github/actions/godot-build/action.yml
vendored
21
.github/actions/godot-build/action.yml
vendored
@ -1,39 +1,34 @@
|
||||
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
|
||||
required: false
|
||||
platform:
|
||||
description: Target platform.
|
||||
required: false
|
||||
sconsflags:
|
||||
description: Additional SCons flags.
|
||||
default: ''
|
||||
required: false
|
||||
default: ""
|
||||
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 }}
|
||||
|
||||
|
19
.github/actions/godot-cache-restore/action.yml
vendored
19
.github/actions/godot-cache-restore/action.yml
vendored
@ -3,19 +3,18 @@ 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
|
||||
@ -29,7 +28,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}}
|
||||
|
11
.github/actions/godot-cache-save/action.yml
vendored
11
.github/actions/godot-cache-save/action.yml
vendored
@ -3,16 +3,15 @@ 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,13 +1,11 @@
|
||||
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
|
||||
|
10
.github/actions/godot-deps/action.yml
vendored
10
.github/actions/godot-deps/action.yml
vendored
@ -1,19 +1,17 @@
|
||||
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,13 +1,11 @@
|
||||
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
|
||||
|
8
.github/actions/upload-artifact/action.yml
vendored
8
.github/actions/upload-artifact/action.yml
vendored
@ -1,17 +1,15 @@
|
||||
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
|
||||
|
12
.github/workflows/android_builds.yml
vendored
12
.github/workflows/android_builds.yml
vendored
@ -5,16 +5,16 @@ on:
|
||||
# Global Settings
|
||||
env:
|
||||
# Used for the cache key. Add version suffix to force clean build.
|
||||
GODOT_BASE_BRANCH: master
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no module_text_server_fb_enabled=yes strict_checks=yes
|
||||
GODOT_BASE_BRANCH: 4.3
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no module_text_server_fb_enabled=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,8 +39,7 @@ jobs:
|
||||
sconsflags: arch=arm64
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@ -86,7 +85,6 @@ jobs:
|
||||
run: |
|
||||
cd platform/android/java
|
||||
./gradlew generateGodotEditor
|
||||
./gradlew generateGodotHorizonOSEditor
|
||||
cd ../../..
|
||||
ls -l bin/android_editor_builds/
|
||||
|
||||
|
64
.github/workflows/godot_cpp_test.yml
vendored
64
.github/workflows/godot_cpp_test.yml
vendored
@ -5,60 +5,54 @@ on:
|
||||
# Global Settings
|
||||
env:
|
||||
# Used for the cache key. Add version suffix to force clean build.
|
||||
GODOT_BASE_BRANCH: master
|
||||
GODOT_BASE_BRANCH: 4.3
|
||||
# Used for the godot-cpp checkout.
|
||||
GODOT_CPP_BRANCH: 4.3
|
||||
GODOT_CPP_BRANCH: '4.2'
|
||||
|
||||
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:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: .github
|
||||
|
||||
- name: Checkout godot-cpp
|
||||
uses: actions/checkout@v4
|
||||
- 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
|
||||
|
||||
- name: Setup GCC problem matcher
|
||||
uses: ammaraskar/gcc-problem-matcher@master
|
||||
# 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'
|
||||
|
||||
# Download generated API dump
|
||||
- name: Download GDExtension interface and API dump
|
||||
uses: ./.github/actions/download-artifact
|
||||
with:
|
||||
name: godot-api-dump
|
||||
path: ./godot-cpp/gdextension
|
||||
name: 'godot-api-dump'
|
||||
path: './godot-api'
|
||||
|
||||
# TODO: Enable caching when godot-cpp has proper cache limiting.
|
||||
# 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/
|
||||
|
||||
# - name: Restore Godot build cache
|
||||
# uses: ./.github/actions/godot-cache-restore
|
||||
# with:
|
||||
# cache-name: godot-cpp
|
||||
# continue-on-error: true
|
||||
# TODO: Add caching to the SCons build and store it for CI via the godot-cache
|
||||
# action.
|
||||
|
||||
# Build godot-cpp test extension
|
||||
- name: Build godot-cpp test extension
|
||||
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
|
||||
|
||||
# - name: Save Godot build cache
|
||||
# uses: ./.github/actions/godot-cache-save
|
||||
# with:
|
||||
# cache-name: godot-cpp
|
||||
# continue-on-error: true
|
||||
run: |
|
||||
cd godot-cpp/test
|
||||
scons target=template_debug dev_build=yes
|
||||
cd ../..
|
||||
|
11
.github/workflows/ios_builds.yml
vendored
11
.github/workflows/ios_builds.yml
vendored
@ -5,21 +5,20 @@ on:
|
||||
# Global Settings
|
||||
env:
|
||||
# Used for the cache key. Add version suffix to force clean build.
|
||||
GODOT_BASE_BRANCH: master
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no module_text_server_fb_enabled=yes strict_checks=yes
|
||||
GODOT_BASE_BRANCH: 4.3
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no module_text_server_fb_enabled=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:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
59
.github/workflows/linux_builds.yml
vendored
59
.github/workflows/linux_builds.yml
vendored
@ -5,19 +5,19 @@ on:
|
||||
# Global Settings
|
||||
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 strict_checks=yes
|
||||
GODOT_BASE_BRANCH: 4.3
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes
|
||||
DOTNET_NOLOGO: true
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: true
|
||||
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,37 +66,36 @@ 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, tests=yes)
|
||||
- name: Template w/ Mono (target=template_release)
|
||||
cache-name: linux-template-mono
|
||||
target: template_release
|
||||
sconsflags: module_mono_enabled=yes
|
||||
bin: ./bin/godot.linuxbsd.template_release.x86_64.mono
|
||||
sconsflags: module_mono_enabled=yes tests=yes
|
||||
bin: "./bin/godot.linuxbsd.template_release.x86_64.mono"
|
||||
build-mono: false
|
||||
tests: true
|
||||
artifact: true
|
||||
|
||||
- name: Minimal template (target=template_release, tests=yes, everything disabled)
|
||||
- name: Minimal template (target=template_release, 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
|
||||
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 tests=yes
|
||||
bin: "./bin/godot.linuxbsd.template_release.x86_64"
|
||||
tests: true
|
||||
artifact: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- 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
|
||||
@ -121,11 +120,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.
|
||||
@ -150,48 +149,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"
|
||||
@ -200,20 +199,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 }}
|
||||
|
21
.github/workflows/macos_builds.yml
vendored
21
.github/workflows/macos_builds.yml
vendored
@ -5,16 +5,16 @@ on:
|
||||
# Global Settings
|
||||
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 strict_checks=yes
|
||||
GODOT_BASE_BRANCH: 4.3
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=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,18 +24,17 @@ 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, tests=yes)
|
||||
- name: Template (target=template_release)
|
||||
cache-name: macos-template
|
||||
target: template_release
|
||||
tests: true
|
||||
sconsflags: debug_symbols=no
|
||||
bin: ./bin/godot.macos.template_release.universal
|
||||
sconsflags: debug_symbols=no tests=yes
|
||||
bin: "./bin/godot.macos.template_release.universal"
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@ -87,7 +86,7 @@ jobs:
|
||||
name: ${{ matrix.cache-name }}
|
||||
|
||||
- name: Unit tests
|
||||
if: matrix.tests
|
||||
if: ${{ matrix.tests }}
|
||||
run: |
|
||||
${{ matrix.bin }} --version
|
||||
${{ matrix.bin }} --help
|
||||
|
13
.github/workflows/runner.yml
vendored
13
.github/workflows/runner.yml
vendored
@ -1,46 +1,52 @@
|
||||
name: 🔗 GHA
|
||||
on: [push, pull_request, merge_group]
|
||||
on: [push, pull_request]
|
||||
|
||||
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
|
||||
@ -50,6 +56,7 @@ 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
|
||||
|
8
.github/workflows/static_checks.yml
vendored
8
.github/workflows/static_checks.yml
vendored
@ -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: --files ${{ env.CHANGED_FILES }}
|
||||
extra_args: --verbose --files ${{ env.CHANGED_FILES }}
|
||||
|
||||
- name: Python builders checks via pytest
|
||||
run: |
|
||||
@ -57,7 +57,3 @@ 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
|
||||
|
21
.github/workflows/web_builds.yml
vendored
21
.github/workflows/web_builds.yml
vendored
@ -5,18 +5,18 @@ on:
|
||||
# Global Settings
|
||||
env:
|
||||
# Used for the cache key. Add version suffix to force clean build.
|
||||
GODOT_BASE_BRANCH: master
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no use_closure_compiler=yes strict_checks=yes
|
||||
GODOT_BASE_BRANCH: 4.3
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes debug_symbols=no use_closure_compiler=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,17 +37,16 @@ jobs:
|
||||
artifact: true
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- 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: |
|
||||
@ -78,6 +77,6 @@ jobs:
|
||||
|
||||
- name: Upload artifact
|
||||
uses: ./.github/actions/upload-artifact
|
||||
if: matrix.artifact
|
||||
if: ${{ matrix.artifact }}
|
||||
with:
|
||||
name: ${{ matrix.cache-name }}
|
||||
|
34
.github/workflows/windows_builds.yml
vendored
34
.github/workflows/windows_builds.yml
vendored
@ -6,18 +6,18 @@ on:
|
||||
# SCONS_CACHE for windows must be set in the build environment
|
||||
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 }}/"
|
||||
GODOT_BASE_BRANCH: 4.3
|
||||
SCONSFLAGS: verbose=yes warnings=extra werror=yes module_text_server_fb_enabled=yes d3d12=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,27 +29,17 @@ 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
|
||||
artifact: true
|
||||
bin: "./bin/godot.windows.editor.x86_64.exe"
|
||||
|
||||
- name: Editor w/ clang-cl (target=editor, tests=yes, use_llvm=yes)
|
||||
cache-name: windows-editor-clang
|
||||
target: editor
|
||||
tests: true
|
||||
sconsflags: debug_symbols=no windows_subsystem=console use_llvm=yes
|
||||
bin: ./bin/godot.windows.editor.x86_64.llvm.exe
|
||||
|
||||
- name: Template (target=template_release, tests=yes)
|
||||
- name: Template (target=template_release)
|
||||
cache-name: windows-template
|
||||
target: template_release
|
||||
tests: true
|
||||
sconsflags: debug_symbols=no
|
||||
bin: ./bin/godot.windows.template_release.x86_64.console.exe
|
||||
artifact: true
|
||||
sconsflags: debug_symbols=no tests=yes
|
||||
bin: "./bin/godot.windows.template_release.x86_64.console.exe"
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@ -74,7 +64,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
|
||||
@ -94,18 +84,16 @@ jobs:
|
||||
continue-on-error: true
|
||||
|
||||
- name: Prepare artifact
|
||||
if: ${{ matrix.artifact }}
|
||||
run: |
|
||||
Remove-Item bin/* -Include *.exp,*.lib,*.pdb -Force
|
||||
|
||||
- name: Upload artifact
|
||||
if: ${{ matrix.artifact }}
|
||||
uses: ./.github/actions/upload-artifact
|
||||
with:
|
||||
name: ${{ matrix.cache-name }}
|
||||
|
||||
- name: Unit tests
|
||||
if: matrix.tests
|
||||
if: ${{ matrix.tests }}
|
||||
run: |
|
||||
${{ matrix.bin }} --version
|
||||
${{ matrix.bin }} --help
|
||||
|
@ -9,7 +9,7 @@ exclude: |
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v19.1.0
|
||||
rev: v17.0.6
|
||||
hooks:
|
||||
- id: clang-format
|
||||
files: \.(c|h|cpp|hpp|cc|hh|cxx|hxx|m|mm|inc|java|glsl)$
|
||||
@ -17,7 +17,6 @@ repos:
|
||||
exclude: |
|
||||
(?x)^(
|
||||
tests/python_build/.*|
|
||||
platform/android/java/editor/src/main/java/com/android/.*|
|
||||
platform/android/java/lib/src/com/.*
|
||||
)
|
||||
|
||||
@ -31,7 +30,6 @@ repos:
|
||||
exclude: |
|
||||
(?x)^(
|
||||
tests/python_build/.*|
|
||||
platform/android/java/editor/src/main/java/com/android/.*|
|
||||
platform/android/java/lib/src/com/.*
|
||||
)
|
||||
additional_dependencies: [clang-tidy==18.1.1]
|
||||
@ -39,14 +37,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.6.6
|
||||
rev: v0.4.4
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--fix]
|
||||
- id: ruff-format
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.11.2
|
||||
rev: v0.971
|
||||
hooks:
|
||||
- id: mypy
|
||||
files: \.py$
|
||||
@ -56,11 +54,6 @@ repos:
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: codespell
|
||||
exclude: |
|
||||
(?x)^(
|
||||
platform/android/java/editor/src/main/java/com/android/.*|
|
||||
platform/android/java/lib/src/com/.*
|
||||
)
|
||||
additional_dependencies: [tomli]
|
||||
|
||||
### Requires Docker; look into alternative implementation.
|
||||
@ -96,21 +89,16 @@ 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
|
||||
@ -128,7 +116,7 @@ repos:
|
||||
- -d
|
||||
- dry-run
|
||||
pass_filenames: false
|
||||
additional_dependencies: [jsdoc@^4.0.3]
|
||||
additional_dependencies: ['jsdoc@^4.0.3']
|
||||
|
||||
- id: svgo
|
||||
name: svgo
|
||||
@ -136,7 +124,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
|
||||
@ -147,7 +135,6 @@ repos:
|
||||
(?x)^(
|
||||
core/math/bvh_.*\.inc$|
|
||||
platform/(?!android|ios|linuxbsd|macos|web|windows)\w+/.*|
|
||||
platform/android/java/editor/src/main/java/com/android/.*|
|
||||
platform/android/java/lib/src/com/.*|
|
||||
platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView\.java$|
|
||||
platform/android/java/lib/src/org/godotengine/godot/gl/EGLLogWrapper\.java$|
|
||||
@ -175,7 +162,6 @@ repos:
|
||||
modules/gdscript/tests/scripts/parser/features/mixed_indentation_on_blank_lines\.gd$|
|
||||
modules/gdscript/tests/scripts/parser/warnings/empty_file_newline_comment\.notest\.gd$|
|
||||
modules/gdscript/tests/scripts/parser/warnings/empty_file_newline\.notest\.gd$|
|
||||
platform/android/java/editor/src/main/java/com/android/.*|
|
||||
platform/android/java/lib/src/com/google/.*
|
||||
)
|
||||
|
||||
@ -184,7 +170,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,
|
||||
|
@ -63,44 +63,6 @@ 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
|
||||
@ -108,8 +70,7 @@ Copyright: 2020, Manuel Prandini
|
||||
2007-2014, Juan Linietsky, Ariel Manzur
|
||||
License: Expat
|
||||
|
||||
Files: ./platform/android/java/editor/src/main/java/com/android/*
|
||||
./platform/android/java/lib/aidl/com/android/*
|
||||
Files: ./platform/android/java/lib/aidl/com/android/*
|
||||
./platform/android/java/lib/res/layout/status_bar_ongoing_event_progress_bar.xml
|
||||
./platform/android/java/lib/src/com/google/android/*
|
||||
./platform/android/java/lib/src/org/godotengine/godot/input/InputManagerCompat.java
|
||||
@ -131,6 +92,44 @@ 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
|
||||
@ -476,11 +475,6 @@ Comment: RVO2
|
||||
Copyright: 2016, University of North Carolina at Chapel Hill
|
||||
License: Apache-2.0
|
||||
|
||||
Files: ./thirdparty/spirv-cross/
|
||||
Comment: SPIRV-Cross
|
||||
Copyright: 2015-2021, Arm Limited
|
||||
License: Apache-2.0 or Expat
|
||||
|
||||
Files: ./thirdparty/spirv-reflect/
|
||||
Comment: SPIRV-Reflect
|
||||
Copyright: 2017-2022, Google Inc.
|
||||
|
153
SConstruct
153
SConstruct
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
EnsureSConsVersion(3, 1, 2)
|
||||
EnsurePythonVersion(3, 6)
|
||||
@ -219,11 +218,10 @@ opts.Add(BoolVariable("deprecated", "Enable compatibility code for deprecated an
|
||||
opts.Add(EnumVariable("precision", "Set the floating-point precision level", "single", ("single", "double")))
|
||||
opts.Add(BoolVariable("minizip", "Enable ZIP archive support using minizip", True))
|
||||
opts.Add(BoolVariable("brotli", "Enable Brotli for decompresson and WOFF2 fonts support", True))
|
||||
opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver on supported platforms", False))
|
||||
opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver", False))
|
||||
opts.Add(BoolVariable("vulkan", "Enable the vulkan rendering driver", True))
|
||||
opts.Add(BoolVariable("opengl3", "Enable the OpenGL/GLES3 rendering driver", True))
|
||||
opts.Add(BoolVariable("d3d12", "Enable the Direct3D 12 rendering driver on supported platforms", False))
|
||||
opts.Add(BoolVariable("metal", "Enable the Metal rendering driver on supported platforms (Apple arm64 only)", False))
|
||||
opts.Add(BoolVariable("d3d12", "Enable the Direct3D 12 rendering driver", False))
|
||||
opts.Add(BoolVariable("openxr", "Enable the OpenXR driver", True))
|
||||
opts.Add(BoolVariable("use_volk", "Use the volk library to load the Vulkan loader dynamically", True))
|
||||
opts.Add(BoolVariable("disable_exceptions", "Force disabling exception handling code", True))
|
||||
@ -231,22 +229,11 @@ opts.Add("custom_modules", "A list of comma-separated directory paths containing
|
||||
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
|
||||
|
||||
# Advanced options
|
||||
opts.Add(
|
||||
BoolVariable(
|
||||
"dev_mode", "Alias for dev options: verbose=yes warnings=extra werror=yes tests=yes strict_checks=yes", False
|
||||
)
|
||||
)
|
||||
opts.Add(BoolVariable("dev_mode", "Alias for dev options: verbose=yes warnings=extra werror=yes tests=yes", False))
|
||||
opts.Add(BoolVariable("tests", "Build the unit tests", False))
|
||||
opts.Add(BoolVariable("fast_unsafe", "Enable unsafe options for faster rebuilds", False))
|
||||
opts.Add(BoolVariable("ninja", "Use the ninja backend for faster rebuilds", False))
|
||||
opts.Add(BoolVariable("ninja_auto_run", "Run ninja automatically after generating the ninja file", True))
|
||||
opts.Add("ninja_file", "Path to the generated ninja file", "build.ninja")
|
||||
opts.Add(BoolVariable("compiledb", "Generate compilation DB (`compile_commands.json`) for external tools", False))
|
||||
opts.Add(
|
||||
"num_jobs",
|
||||
"Use up to N jobs when compiling (equivalent to `-j N`). Defaults to max jobs - 1. Ignored if -j is used.",
|
||||
"",
|
||||
)
|
||||
opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False))
|
||||
opts.Add(BoolVariable("progress", "Show a progress indicator during compilation", True))
|
||||
opts.Add(EnumVariable("warnings", "Level of compilation warnings", "all", ("extra", "all", "moderate", "no")))
|
||||
@ -267,7 +254,6 @@ opts.Add(
|
||||
"",
|
||||
)
|
||||
opts.Add(BoolVariable("use_precise_math_checks", "Math checks use very precise epsilon (debug option)", False))
|
||||
opts.Add(BoolVariable("strict_checks", "Enforce stricter checks (debug option)", False))
|
||||
opts.Add(BoolVariable("scu_build", "Use single compilation unit build", False))
|
||||
opts.Add("scu_limit", "Max includes per SCU file when using scu_build (determines RAM use)", "0")
|
||||
opts.Add(BoolVariable("engine_update_check", "Enable engine update checks in the Project Manager", True))
|
||||
@ -299,6 +285,7 @@ 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))
|
||||
@ -550,22 +537,16 @@ initial_num_jobs = env.GetOption("num_jobs")
|
||||
altered_num_jobs = initial_num_jobs + 1
|
||||
env.SetOption("num_jobs", altered_num_jobs)
|
||||
if env.GetOption("num_jobs") == altered_num_jobs:
|
||||
num_jobs = env.get("num_jobs", "")
|
||||
if str(num_jobs).isdigit() and int(num_jobs) > 0:
|
||||
env.SetOption("num_jobs", num_jobs)
|
||||
cpu_count = os.cpu_count()
|
||||
if cpu_count is None:
|
||||
print_warning("Couldn't auto-detect CPU count to configure build parallelism. Specify it with the -j argument.")
|
||||
else:
|
||||
cpu_count = os.cpu_count()
|
||||
if cpu_count is None:
|
||||
print_warning(
|
||||
"Couldn't auto-detect CPU count to configure build parallelism. Specify it with the `-j` or `num_jobs` arguments."
|
||||
)
|
||||
else:
|
||||
safer_cpu_count = cpu_count if cpu_count <= 4 else cpu_count - 1
|
||||
print(
|
||||
"Auto-detected %d CPU cores available for build parallelism. Using %d cores by default. You can override it with the `-j` or `num_jobs` arguments."
|
||||
% (cpu_count, safer_cpu_count)
|
||||
)
|
||||
env.SetOption("num_jobs", safer_cpu_count)
|
||||
safer_cpu_count = cpu_count if cpu_count <= 4 else cpu_count - 1
|
||||
print(
|
||||
"Auto-detected %d CPU cores available for build parallelism. Using %d cores by default. You can override it with the -j argument."
|
||||
% (cpu_count, safer_cpu_count)
|
||||
)
|
||||
env.SetOption("num_jobs", safer_cpu_count)
|
||||
|
||||
env.extra_suffix = ""
|
||||
|
||||
@ -607,16 +588,12 @@ if env["dev_mode"]:
|
||||
env["warnings"] = ARGUMENTS.get("warnings", "extra")
|
||||
env["werror"] = methods.get_cmdline_bool("werror", True)
|
||||
env["tests"] = methods.get_cmdline_bool("tests", True)
|
||||
env["strict_checks"] = methods.get_cmdline_bool("strict_checks", True)
|
||||
if env["production"]:
|
||||
env["use_static_cpp"] = methods.get_cmdline_bool("use_static_cpp", True)
|
||||
env["debug_symbols"] = methods.get_cmdline_bool("debug_symbols", False)
|
||||
# LTO "auto" means we handle the preferred option in each platform detect.py.
|
||||
env["lto"] = ARGUMENTS.get("lto", "auto")
|
||||
|
||||
if env["strict_checks"]:
|
||||
env.Append(CPPDEFINES=["STRICT_CHECKS"])
|
||||
|
||||
# Run SCU file generation script if in a SCU build.
|
||||
if env["scu_build"]:
|
||||
max_includes_per_scu = 8
|
||||
@ -639,18 +616,25 @@ 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)
|
||||
cc_version_major = cc_version["major"]
|
||||
cc_version_minor = cc_version["minor"]
|
||||
cc_version_metadata1 = cc_version["metadata1"]
|
||||
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 ""
|
||||
|
||||
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:
|
||||
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:
|
||||
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 "
|
||||
@ -670,12 +654,17 @@ elif 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
|
||||
if env["platform"] == "macos" or env["platform"] == "ios":
|
||||
elif env["platform"] == "macos" or env["platform"] == "ios":
|
||||
vanilla = methods.is_vanilla_clang(env)
|
||||
if vanilla and cc_version_major < 6:
|
||||
print_error(
|
||||
print_warning(
|
||||
"Detected Clang version older than 6, which does not fully support "
|
||||
"C++17. Supported versions are Clang 6 and later."
|
||||
)
|
||||
@ -700,28 +689,6 @@ 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.
|
||||
@ -799,23 +766,13 @@ 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++17.
|
||||
# both GCC and Clang. Both currently default to gnu11 and gnu++14.
|
||||
env.Prepend(CFLAGS=["-std=gnu11"])
|
||||
env.Prepend(CXXFLAGS=["-std=gnu++17"])
|
||||
else:
|
||||
# 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.
|
||||
env.Prepend(CCFLAGS=["/permissive-"])
|
||||
# Allow use of `__cplusplus` macro to determine C++ standard universally.
|
||||
env.Prepend(CXXFLAGS=["/Zc:__cplusplus"])
|
||||
# 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"])
|
||||
|
||||
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
|
||||
# saves around 20% of binary size and very significant build time (GH-80513).
|
||||
@ -828,7 +785,7 @@ elif env.msvc:
|
||||
env.Append(CXXFLAGS=["/EHsc"])
|
||||
|
||||
# Configure compiler warnings
|
||||
if env.msvc and not methods.using_clang(env): # MSVC
|
||||
if env.msvc: # MSVC
|
||||
if env["warnings"] == "no":
|
||||
env.Append(CCFLAGS=["/w"])
|
||||
else:
|
||||
@ -878,11 +835,8 @@ else: # GCC, Clang
|
||||
# for putting them in `Set` or `Map`. We don't mind about unreliable ordering.
|
||||
common_warnings += ["-Wno-ordered-compare-function-pointers"]
|
||||
|
||||
# clang-cl will interpret `-Wall` as `-Weverything`, workaround with compatibility cast
|
||||
W_ALL = "-Wall" if not env.msvc else "-W3"
|
||||
|
||||
if env["warnings"] == "extra":
|
||||
env.Append(CCFLAGS=[W_ALL, "-Wextra", "-Wwrite-strings", "-Wno-unused-parameter"] + common_warnings)
|
||||
env.Append(CCFLAGS=["-Wall", "-Wextra", "-Wwrite-strings", "-Wno-unused-parameter"] + common_warnings)
|
||||
env.Append(CXXFLAGS=["-Wctor-dtor-privacy", "-Wnon-virtual-dtor"])
|
||||
if methods.using_gcc(env):
|
||||
env.Append(
|
||||
@ -904,9 +858,9 @@ else: # GCC, Clang
|
||||
elif methods.using_clang(env) or methods.using_emcc(env):
|
||||
env.Append(CCFLAGS=["-Wimplicit-fallthrough"])
|
||||
elif env["warnings"] == "all":
|
||||
env.Append(CCFLAGS=[W_ALL] + common_warnings)
|
||||
env.Append(CCFLAGS=["-Wall"] + common_warnings)
|
||||
elif env["warnings"] == "moderate":
|
||||
env.Append(CCFLAGS=[W_ALL, "-Wno-unused"] + common_warnings)
|
||||
env.Append(CCFLAGS=["-Wall", "-Wno-unused"] + common_warnings)
|
||||
else: # 'no'
|
||||
env.Append(CCFLAGS=["-w"])
|
||||
|
||||
@ -1060,9 +1014,7 @@ if env["vsproj"]:
|
||||
if env["compiledb"]:
|
||||
if env.scons_version < (4, 0, 0):
|
||||
# Generating the compilation DB (`compile_commands.json`) requires SCons 4.0.0 or later.
|
||||
print_error(
|
||||
"The `compiledb=yes` option requires SCons 4.0 or later, but your version is %s." % scons_raw_version
|
||||
)
|
||||
print_error("The `compiledb=yes` option requires SCons 4.0 or later, but your version is %s." % scons_raw_version)
|
||||
Exit(255)
|
||||
|
||||
env.Tool("compilation_db")
|
||||
@ -1074,9 +1026,12 @@ if env["ninja"]:
|
||||
Exit(255)
|
||||
|
||||
SetOption("experimental", "ninja")
|
||||
env["NINJA_FILE_NAME"] = env["ninja_file"]
|
||||
env["NINJA_DISABLE_AUTO_RUN"] = not env["ninja_auto_run"]
|
||||
env.Tool("ninja", "build.ninja")
|
||||
env.Tool("ninja")
|
||||
|
||||
# By setting this we allow the user to run ninja by themselves with all
|
||||
# the flags they need, as apparently automatically running from scons
|
||||
# is way slower.
|
||||
SetOption("disable_execute_ninja", True)
|
||||
|
||||
# Threads
|
||||
if env["threads"]:
|
||||
@ -1138,7 +1093,7 @@ atexit.register(print_elapsed_time)
|
||||
|
||||
|
||||
def purge_flaky_files():
|
||||
paths_to_keep = ["build.ninja"]
|
||||
paths_to_keep = ["ninja.build"]
|
||||
for build_failure in GetBuildFailures():
|
||||
path = build_failure.node.path
|
||||
if os.path.isfile(path) and path not in paths_to_keep:
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
@ -263,18 +263,6 @@ bool Engine::is_generate_spirv_debug_info_enabled() const {
|
||||
return generate_spirv_debug_info;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -72,7 +72,6 @@ private:
|
||||
bool abort_on_gpu_errors = false;
|
||||
bool use_validation_layers = false;
|
||||
bool generate_spirv_debug_info = false;
|
||||
bool extra_gpu_memory_tracking = false;
|
||||
int32_t gpu_idx = -1;
|
||||
|
||||
uint64_t _process_frames = 0;
|
||||
@ -128,9 +127,6 @@ 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;
|
||||
@ -185,7 +181,6 @@ public:
|
||||
bool is_abort_on_gpu_errors_enabled() const;
|
||||
bool is_validation_layers_enabled() const;
|
||||
bool is_generate_spirv_debug_info_enabled() const;
|
||||
bool is_extra_gpu_memory_tracking_enabled() const;
|
||||
int32_t get_gpu_index() const;
|
||||
|
||||
void increment_frames_drawn();
|
||||
|
@ -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(get_resource_path())) {
|
||||
if (_csproj_exists(p_path.get_base_dir())) {
|
||||
// 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#");
|
||||
@ -1472,6 +1472,10 @@ ProjectSettings::ProjectSettings() {
|
||||
GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_height_override", PROPERTY_HINT_RANGE, "0,4320,1,or_greater"), 0); // 8K resolution
|
||||
|
||||
GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true);
|
||||
#ifdef TOOLS_ENABLED
|
||||
GLOBAL_DEF("display/window/energy_saving/keep_screen_on.editor_hint", false);
|
||||
#endif
|
||||
|
||||
GLOBAL_DEF("animation/warnings/check_invalid_track_paths", true);
|
||||
GLOBAL_DEF("animation/warnings/check_angle_interpolation_type_conflicting", true);
|
||||
|
||||
@ -1557,11 +1561,6 @@ ProjectSettings::ProjectSettings() {
|
||||
|
||||
GLOBAL_DEF("collada/use_ambient", false);
|
||||
|
||||
// Input settings
|
||||
GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_long_press_as_right_click", false);
|
||||
GLOBAL_DEF_BASIC("input_devices/pointing/android/enable_pan_and_scale_gestures", false);
|
||||
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "input_devices/pointing/android/rotary_input_scroll_axis", PROPERTY_HINT_ENUM, "Horizontal,Vertical"), 1);
|
||||
|
||||
// These properties will not show up in the dialog. If you want to exclude whole groups, use add_hidden_prefix().
|
||||
GLOBAL_DEF_INTERNAL("application/config/features", PackedStringArray());
|
||||
GLOBAL_DEF_INTERNAL("internationalization/locale/translation_remaps", PackedStringArray());
|
||||
@ -1574,7 +1573,6 @@ ProjectSettings::ProjectSettings() {
|
||||
|
||||
ProjectSettings::ProjectSettings(const String &p_path) {
|
||||
if (load_custom(p_path) == OK) {
|
||||
resource_path = p_path.get_base_dir();
|
||||
project_loaded = true;
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,6 @@
|
||||
/**************************************************************************/
|
||||
|
||||
#include "core_bind.h"
|
||||
#include "core_bind.compat.inc"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/crypto/crypto_core.h"
|
||||
@ -57,11 +56,8 @@ Error ResourceLoader::load_threaded_request(const String &p_path, const String &
|
||||
ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const String &p_path, Array r_progress) {
|
||||
float progress = 0;
|
||||
::ResourceLoader::ThreadLoadStatus tls = ::ResourceLoader::load_threaded_get_status(p_path, &progress);
|
||||
// Default array should never be modified, it causes the hash of the method to change.
|
||||
if (!ClassDB::is_default_array_arg(r_progress)) {
|
||||
r_progress.resize(1);
|
||||
r_progress[0] = progress;
|
||||
}
|
||||
r_progress.resize(1);
|
||||
r_progress[0] = progress;
|
||||
return (ThreadLoadStatus)tls;
|
||||
}
|
||||
|
||||
@ -119,11 +115,6 @@ bool ResourceLoader::has_cached(const String &p_path) {
|
||||
return ResourceCache::has(local_path);
|
||||
}
|
||||
|
||||
Ref<Resource> ResourceLoader::get_cached_ref(const String &p_path) {
|
||||
String local_path = ProjectSettings::get_singleton()->localize_path(p_path);
|
||||
return ResourceCache::get_ref(local_path);
|
||||
}
|
||||
|
||||
bool ResourceLoader::exists(const String &p_path, const String &p_type_hint) {
|
||||
return ::ResourceLoader::exists(p_path, p_type_hint);
|
||||
}
|
||||
@ -134,7 +125,7 @@ ResourceUID::ID ResourceLoader::get_resource_uid(const String &p_path) {
|
||||
|
||||
void ResourceLoader::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("load_threaded_request", "path", "type_hint", "use_sub_threads", "cache_mode"), &ResourceLoader::load_threaded_request, DEFVAL(""), DEFVAL(false), DEFVAL(CACHE_MODE_REUSE));
|
||||
ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &ResourceLoader::load_threaded_get_status, DEFVAL_ARRAY);
|
||||
ClassDB::bind_method(D_METHOD("load_threaded_get_status", "path", "progress"), &ResourceLoader::load_threaded_get_status, DEFVAL(Array()));
|
||||
ClassDB::bind_method(D_METHOD("load_threaded_get", "path"), &ResourceLoader::load_threaded_get);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("load", "path", "type_hint", "cache_mode"), &ResourceLoader::load, DEFVAL(""), DEFVAL(CACHE_MODE_REUSE));
|
||||
@ -144,7 +135,6 @@ void ResourceLoader::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_abort_on_missing_resources", "abort"), &ResourceLoader::set_abort_on_missing_resources);
|
||||
ClassDB::bind_method(D_METHOD("get_dependencies", "path"), &ResourceLoader::get_dependencies);
|
||||
ClassDB::bind_method(D_METHOD("has_cached", "path"), &ResourceLoader::has_cached);
|
||||
ClassDB::bind_method(D_METHOD("get_cached_ref", "path"), &ResourceLoader::get_cached_ref);
|
||||
ClassDB::bind_method(D_METHOD("exists", "path", "type_hint"), &ResourceLoader::exists, DEFVAL(""));
|
||||
ClassDB::bind_method(D_METHOD("get_resource_uid", "path"), &ResourceLoader::get_resource_uid);
|
||||
|
||||
@ -184,10 +174,6 @@ 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() {
|
||||
@ -195,7 +181,6 @@ 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);
|
||||
@ -315,22 +300,19 @@ int OS::execute(const String &p_path, const Vector<String> &p_arguments, Array r
|
||||
String pipe;
|
||||
int exitcode = 0;
|
||||
Error err = ::OS::get_singleton()->execute(p_path, args, &pipe, &exitcode, p_read_stderr, nullptr, p_open_console);
|
||||
// Default array should never be modified, it causes the hash of the method to change.
|
||||
if (!ClassDB::is_default_array_arg(r_output)) {
|
||||
r_output.push_back(pipe);
|
||||
}
|
||||
r_output.push_back(pipe);
|
||||
if (err != OK) {
|
||||
return -1;
|
||||
}
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
Dictionary OS::execute_with_pipe(const String &p_path, const Vector<String> &p_arguments, bool p_blocking) {
|
||||
Dictionary OS::execute_with_pipe(const String &p_path, const Vector<String> &p_arguments) {
|
||||
List<String> args;
|
||||
for (const String &arg : p_arguments) {
|
||||
args.push_back(arg);
|
||||
}
|
||||
return ::OS::get_singleton()->execute_with_pipe(p_path, args, p_blocking);
|
||||
return ::OS::get_singleton()->execute_with_pipe(p_path, args);
|
||||
}
|
||||
|
||||
int OS::create_instance(const Vector<String> &p_arguments) {
|
||||
@ -629,8 +611,8 @@ void OS::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_system_font_path_for_text", "font_name", "text", "locale", "script", "weight", "stretch", "italic"), &OS::get_system_font_path_for_text, DEFVAL(String()), DEFVAL(String()), DEFVAL(400), DEFVAL(100), DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("get_executable_path"), &OS::get_executable_path);
|
||||
ClassDB::bind_method(D_METHOD("read_string_from_stdin"), &OS::read_string_from_stdin);
|
||||
ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr", "open_console"), &OS::execute, DEFVAL_ARRAY, DEFVAL(false), DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("execute_with_pipe", "path", "arguments", "blocking"), &OS::execute_with_pipe, DEFVAL(true));
|
||||
ClassDB::bind_method(D_METHOD("execute", "path", "arguments", "output", "read_stderr", "open_console"), &OS::execute, DEFVAL(Array()), DEFVAL(false), DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("execute_with_pipe", "path", "arguments"), &OS::execute_with_pipe);
|
||||
ClassDB::bind_method(D_METHOD("create_process", "path", "arguments", "open_console"), &OS::create_process, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("create_instance", "arguments"), &OS::create_instance);
|
||||
ClassDB::bind_method(D_METHOD("kill", "pid"), &OS::kill);
|
||||
@ -710,7 +692,6 @@ void OS::_bind_methods() {
|
||||
BIND_ENUM_CONSTANT(RENDERING_DRIVER_VULKAN);
|
||||
BIND_ENUM_CONSTANT(RENDERING_DRIVER_OPENGL3);
|
||||
BIND_ENUM_CONSTANT(RENDERING_DRIVER_D3D12);
|
||||
BIND_ENUM_CONSTANT(RENDERING_DRIVER_METAL);
|
||||
|
||||
BIND_ENUM_CONSTANT(SYSTEM_DIR_DESKTOP);
|
||||
BIND_ENUM_CONSTANT(SYSTEM_DIR_DCIM);
|
||||
@ -1228,15 +1209,14 @@ bool Semaphore::try_wait() {
|
||||
return semaphore.try_wait();
|
||||
}
|
||||
|
||||
void Semaphore::post(int p_count) {
|
||||
ERR_FAIL_COND(p_count <= 0);
|
||||
semaphore.post(p_count);
|
||||
void Semaphore::post() {
|
||||
semaphore.post();
|
||||
}
|
||||
|
||||
void Semaphore::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("wait"), &Semaphore::wait);
|
||||
ClassDB::bind_method(D_METHOD("try_wait"), &Semaphore::try_wait);
|
||||
ClassDB::bind_method(D_METHOD("post", "count"), &Semaphore::post, DEFVAL(1));
|
||||
ClassDB::bind_method(D_METHOD("post"), &Semaphore::post);
|
||||
}
|
||||
|
||||
////// Mutex //////
|
||||
@ -1424,11 +1404,6 @@ 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);
|
||||
}
|
||||
@ -1465,14 +1440,6 @@ TypedArray<Dictionary> ClassDB::class_get_property_list(const StringName &p_clas
|
||||
return ret;
|
||||
}
|
||||
|
||||
StringName ClassDB::class_get_property_getter(const StringName &p_class, const StringName &p_property) {
|
||||
return ::ClassDB::get_property_getter(p_class, p_property);
|
||||
}
|
||||
|
||||
StringName ClassDB::class_get_property_setter(const StringName &p_class, const StringName &p_property) {
|
||||
return ::ClassDB::get_property_setter(p_class, p_property);
|
||||
}
|
||||
|
||||
Variant ClassDB::class_get_property(Object *p_object, const StringName &p_property) const {
|
||||
Variant ret;
|
||||
::ClassDB::get_property(p_object, p_property, ret);
|
||||
@ -1525,23 +1492,6 @@ TypedArray<Dictionary> ClassDB::class_get_method_list(const StringName &p_class,
|
||||
return ret;
|
||||
}
|
||||
|
||||
Variant ClassDB::class_call_static_method(const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error) {
|
||||
if (p_argcount < 2) {
|
||||
r_call_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
|
||||
return Variant::NIL;
|
||||
}
|
||||
if (!p_arguments[0]->is_string() || !p_arguments[1]->is_string()) {
|
||||
r_call_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
|
||||
return Variant::NIL;
|
||||
}
|
||||
StringName class_ = *p_arguments[0];
|
||||
StringName method = *p_arguments[1];
|
||||
const MethodBind *bind = ::ClassDB::get_method(class_, method);
|
||||
ERR_FAIL_NULL_V_MSG(bind, Variant::NIL, "Cannot find static method.");
|
||||
ERR_FAIL_COND_V_MSG(!bind->is_static(), Variant::NIL, "Method is not static.");
|
||||
return bind->call(nullptr, p_arguments + 2, p_argcount - 2, r_call_error);
|
||||
}
|
||||
|
||||
PackedStringArray ClassDB::class_get_integer_constant_list(const StringName &p_class, bool p_no_inheritance) const {
|
||||
List<String> constants;
|
||||
::ClassDB::get_integer_constant_list(p_class, &constants, p_no_inheritance);
|
||||
@ -1625,7 +1575,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 == "class_get_api_type");
|
||||
pf == "is_class_enabled" || pf == "is_class_enum_bitfield");
|
||||
}
|
||||
if (first_argument_is_class || pf == "is_parent_class") {
|
||||
for (const String &E : get_class_list()) {
|
||||
@ -1646,15 +1596,11 @@ 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));
|
||||
|
||||
::ClassDB::bind_method(D_METHOD("class_get_property_list", "class", "no_inheritance"), &ClassDB::class_get_property_list, DEFVAL(false));
|
||||
::ClassDB::bind_method(D_METHOD("class_get_property_getter", "class", "property"), &ClassDB::class_get_property_getter);
|
||||
::ClassDB::bind_method(D_METHOD("class_get_property_setter", "class", "property"), &ClassDB::class_get_property_setter);
|
||||
::ClassDB::bind_method(D_METHOD("class_get_property", "object", "property"), &ClassDB::class_get_property);
|
||||
::ClassDB::bind_method(D_METHOD("class_set_property", "object", "property", "value"), &ClassDB::class_set_property);
|
||||
|
||||
@ -1666,8 +1612,6 @@ void ClassDB::_bind_methods() {
|
||||
|
||||
::ClassDB::bind_method(D_METHOD("class_get_method_list", "class", "no_inheritance"), &ClassDB::class_get_method_list, DEFVAL(false));
|
||||
|
||||
::ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "class_call_static_method", &ClassDB::class_call_static_method, MethodInfo("class_call_static_method", PropertyInfo(Variant::STRING_NAME, "class"), PropertyInfo(Variant::STRING_NAME, "method")));
|
||||
|
||||
::ClassDB::bind_method(D_METHOD("class_get_integer_constant_list", "class", "no_inheritance"), &ClassDB::class_get_integer_constant_list, DEFVAL(false));
|
||||
|
||||
::ClassDB::bind_method(D_METHOD("class_has_integer_constant", "class", "name"), &ClassDB::class_has_integer_constant);
|
||||
@ -1681,12 +1625,6 @@ 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
|
||||
@ -1800,7 +1738,7 @@ Object *Engine::get_singleton_object(const StringName &p_name) const {
|
||||
|
||||
void Engine::register_singleton(const StringName &p_name, Object *p_object) {
|
||||
ERR_FAIL_COND_MSG(has_singleton(p_name), "Singleton already registered: " + String(p_name));
|
||||
ERR_FAIL_COND_MSG(!String(p_name).is_valid_ascii_identifier(), "Singleton name is not a valid identifier: " + p_name);
|
||||
ERR_FAIL_COND_MSG(!String(p_name).is_valid_identifier(), "Singleton name is not a valid identifier: " + p_name);
|
||||
::Engine::Singleton s;
|
||||
s.class_name = p_name;
|
||||
s.name = p_name;
|
||||
@ -1853,14 +1791,6 @@ 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);
|
||||
}
|
||||
@ -1929,14 +1859,10 @@ 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");
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
static ResourceLoader *get_singleton() { return singleton; }
|
||||
|
||||
Error load_threaded_request(const String &p_path, const String &p_type_hint = "", bool p_use_sub_threads = false, CacheMode p_cache_mode = CACHE_MODE_REUSE);
|
||||
ThreadLoadStatus load_threaded_get_status(const String &p_path, Array r_progress = ClassDB::default_array_arg);
|
||||
ThreadLoadStatus load_threaded_get_status(const String &p_path, Array r_progress = Array());
|
||||
Ref<Resource> load_threaded_get(const String &p_path);
|
||||
|
||||
Ref<Resource> load(const String &p_path, const String &p_type_hint = "", CacheMode p_cache_mode = CACHE_MODE_REUSE);
|
||||
@ -83,7 +83,6 @@ public:
|
||||
void set_abort_on_missing_resources(bool p_abort);
|
||||
PackedStringArray get_dependencies(const String &p_path);
|
||||
bool has_cached(const String &p_path);
|
||||
Ref<Resource> get_cached_ref(const String &p_path);
|
||||
bool exists(const String &p_path, const String &p_type_hint = "");
|
||||
ResourceUID::ID get_resource_uid(const String &p_path);
|
||||
|
||||
@ -116,8 +115,6 @@ 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; }
|
||||
};
|
||||
|
||||
@ -130,18 +127,11 @@ protected:
|
||||
static void _bind_methods();
|
||||
static OS *singleton;
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
Dictionary _execute_with_pipe_bind_compat_94434(const String &p_path, const Vector<String> &p_arguments);
|
||||
|
||||
static void _bind_compatibility_methods();
|
||||
#endif
|
||||
|
||||
public:
|
||||
enum RenderingDriver {
|
||||
RENDERING_DRIVER_VULKAN,
|
||||
RENDERING_DRIVER_OPENGL3,
|
||||
RENDERING_DRIVER_D3D12,
|
||||
RENDERING_DRIVER_METAL,
|
||||
};
|
||||
|
||||
PackedByteArray get_entropy(int p_bytes);
|
||||
@ -168,8 +158,8 @@ public:
|
||||
Vector<String> get_system_font_path_for_text(const String &p_font_name, const String &p_text, const String &p_locale = String(), const String &p_script = String(), int p_weight = 400, int p_stretch = 100, bool p_italic = false) const;
|
||||
String get_executable_path() const;
|
||||
String read_string_from_stdin();
|
||||
int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = ClassDB::default_array_arg, bool p_read_stderr = false, bool p_open_console = false);
|
||||
Dictionary execute_with_pipe(const String &p_path, const Vector<String> &p_arguments, bool p_blocking = true);
|
||||
int execute(const String &p_path, const Vector<String> &p_arguments, Array r_output = Array(), bool p_read_stderr = false, bool p_open_console = false);
|
||||
Dictionary execute_with_pipe(const String &p_path, const Vector<String> &p_arguments);
|
||||
int create_process(const String &p_path, const Vector<String> &p_arguments, bool p_open_console = false);
|
||||
int create_instance(const Vector<String> &p_arguments);
|
||||
Error kill(int p_pid);
|
||||
@ -399,17 +389,12 @@ class Semaphore : public RefCounted {
|
||||
GDCLASS(Semaphore, RefCounted);
|
||||
::Semaphore semaphore;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
void _post_bind_compat_93605();
|
||||
static void _bind_compatibility_methods();
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
public:
|
||||
void wait();
|
||||
bool try_wait();
|
||||
void post(int p_count = 1);
|
||||
void post();
|
||||
};
|
||||
|
||||
class Thread : public RefCounted {
|
||||
@ -449,14 +434,6 @@ 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;
|
||||
@ -465,14 +442,11 @@ 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;
|
||||
|
||||
TypedArray<Dictionary> class_get_property_list(const StringName &p_class, bool p_no_inheritance = false) const;
|
||||
StringName class_get_property_getter(const StringName &p_class, const StringName &p_property);
|
||||
StringName class_get_property_setter(const StringName &p_class, const StringName &p_property);
|
||||
Variant class_get_property(Object *p_object, const StringName &p_property) const;
|
||||
Error class_set_property(Object *p_object, const StringName &p_property, const Variant &p_value) const;
|
||||
|
||||
@ -483,7 +457,6 @@ public:
|
||||
int class_get_method_argument_count(const StringName &p_class, const StringName &p_method, bool p_no_inheritance = false) const;
|
||||
|
||||
TypedArray<Dictionary> class_get_method_list(const StringName &p_class, bool p_no_inheritance = false) const;
|
||||
Variant class_call_static_method(const Variant **p_arguments, int p_argcount, Callable::CallError &r_call_error);
|
||||
|
||||
PackedStringArray class_get_integer_constant_list(const StringName &p_class, bool p_no_inheritance = false) const;
|
||||
bool class_has_integer_constant(const StringName &p_class, const StringName &p_name) const;
|
||||
@ -569,9 +542,6 @@ 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;
|
||||
|
||||
@ -648,6 +618,4 @@ 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
|
||||
|
@ -671,13 +671,11 @@ void register_global_constants() {
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_OBJECTID);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_POINTER);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ARRAY_TYPE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_DICTIONARY_TYPE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALE_ID);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALIZABLE_STRING);
|
||||
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,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
@ -36,10 +36,10 @@
|
||||
|
||||
/// Resources
|
||||
|
||||
CryptoKey *(*CryptoKey::_create)(bool p_notify_postinitialize) = nullptr;
|
||||
CryptoKey *CryptoKey::create(bool p_notify_postinitialize) {
|
||||
CryptoKey *(*CryptoKey::_create)() = nullptr;
|
||||
CryptoKey *CryptoKey::create() {
|
||||
if (_create) {
|
||||
return _create(p_notify_postinitialize);
|
||||
return _create();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -52,10 +52,10 @@ void CryptoKey::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("load_from_string", "string_key", "public_only"), &CryptoKey::load_from_string, DEFVAL(false));
|
||||
}
|
||||
|
||||
X509Certificate *(*X509Certificate::_create)(bool p_notify_postinitialize) = nullptr;
|
||||
X509Certificate *X509Certificate::create(bool p_notify_postinitialize) {
|
||||
X509Certificate *(*X509Certificate::_create)() = nullptr;
|
||||
X509Certificate *X509Certificate::create() {
|
||||
if (_create) {
|
||||
return _create(p_notify_postinitialize);
|
||||
return _create();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -116,10 +116,10 @@ void HMACContext::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("finish"), &HMACContext::finish);
|
||||
}
|
||||
|
||||
HMACContext *(*HMACContext::_create)(bool p_notify_postinitialize) = nullptr;
|
||||
HMACContext *HMACContext::create(bool p_notify_postinitialize) {
|
||||
HMACContext *(*HMACContext::_create)() = nullptr;
|
||||
HMACContext *HMACContext::create() {
|
||||
if (_create) {
|
||||
return _create(p_notify_postinitialize);
|
||||
return _create();
|
||||
}
|
||||
ERR_FAIL_V_MSG(nullptr, "HMACContext is not available when the mbedtls module is disabled.");
|
||||
}
|
||||
@ -127,10 +127,10 @@ HMACContext *HMACContext::create(bool p_notify_postinitialize) {
|
||||
/// Crypto
|
||||
|
||||
void (*Crypto::_load_default_certificates)(const String &p_path) = nullptr;
|
||||
Crypto *(*Crypto::_create)(bool p_notify_postinitialize) = nullptr;
|
||||
Crypto *Crypto::create(bool p_notify_postinitialize) {
|
||||
Crypto *(*Crypto::_create)() = nullptr;
|
||||
Crypto *Crypto::create() {
|
||||
if (_create) {
|
||||
return _create(p_notify_postinitialize);
|
||||
return _create();
|
||||
}
|
||||
ERR_FAIL_V_MSG(nullptr, "Crypto is not available when the mbedtls module is disabled.");
|
||||
}
|
||||
|
@ -42,10 +42,10 @@ class CryptoKey : public Resource {
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static CryptoKey *(*_create)(bool p_notify_postinitialize);
|
||||
static CryptoKey *(*_create)();
|
||||
|
||||
public:
|
||||
static CryptoKey *create(bool p_notify_postinitialize = true);
|
||||
static CryptoKey *create();
|
||||
virtual Error load(const String &p_path, bool p_public_only = false) = 0;
|
||||
virtual Error save(const String &p_path, bool p_public_only = false) = 0;
|
||||
virtual String save_to_string(bool p_public_only = false) = 0;
|
||||
@ -58,10 +58,10 @@ class X509Certificate : public Resource {
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static X509Certificate *(*_create)(bool p_notify_postinitialize);
|
||||
static X509Certificate *(*_create)();
|
||||
|
||||
public:
|
||||
static X509Certificate *create(bool p_notify_postinitialize = true);
|
||||
static X509Certificate *create();
|
||||
virtual Error load(const String &p_path) = 0;
|
||||
virtual Error load_from_memory(const uint8_t *p_buffer, int p_len) = 0;
|
||||
virtual Error save(const String &p_path) = 0;
|
||||
@ -106,10 +106,10 @@ class HMACContext : public RefCounted {
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static HMACContext *(*_create)(bool p_notify_postinitialize);
|
||||
static HMACContext *(*_create)();
|
||||
|
||||
public:
|
||||
static HMACContext *create(bool p_notify_postinitialize = true);
|
||||
static HMACContext *create();
|
||||
|
||||
virtual Error start(HashingContext::HashType p_hash_type, const PackedByteArray &p_key) = 0;
|
||||
virtual Error update(const PackedByteArray &p_data) = 0;
|
||||
@ -124,11 +124,11 @@ class Crypto : public RefCounted {
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
static Crypto *(*_create)(bool p_notify_postinitialize);
|
||||
static Crypto *(*_create)();
|
||||
static void (*_load_default_certificates)(const String &p_path);
|
||||
|
||||
public:
|
||||
static Crypto *create(bool p_notify_postinitialize = true);
|
||||
static Crypto *create();
|
||||
static void load_default_certificates(const String &p_path);
|
||||
|
||||
virtual PackedByteArray generate_random_bytes(int p_bytes) = 0;
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
@ -144,8 +144,9 @@ void RemoteDebuggerPeerTCP::_read_in() {
|
||||
Error err = decode_variant(var, buf, in_pos, &read);
|
||||
ERR_CONTINUE(read != in_pos || err != OK);
|
||||
ERR_CONTINUE_MSG(var.get_type() != Variant::ARRAY, "Malformed packet received, not an Array.");
|
||||
MutexLock lock(mutex);
|
||||
mutex.lock();
|
||||
in_queue.push_back(var);
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,6 @@
|
||||
String DocData::get_default_value_string(const Variant &p_value) {
|
||||
if (p_value.get_type() == Variant::ARRAY) {
|
||||
return Variant(Array(p_value, 0, StringName(), Variant())).get_construct_string().replace("\n", " ");
|
||||
} else if (p_value.get_type() == Variant::DICTIONARY) {
|
||||
return Variant(Dictionary(p_value, 0, StringName(), Variant(), 0, StringName(), Variant())).get_construct_string().replace("\n", " ");
|
||||
} else {
|
||||
return p_value.get_construct_string().replace("\n", " ");
|
||||
}
|
||||
@ -59,8 +57,6 @@ void DocData::return_doc_from_retinfo(DocData::MethodDoc &p_method, const Proper
|
||||
p_method.return_type = p_retinfo.class_name;
|
||||
} else if (p_retinfo.type == Variant::ARRAY && p_retinfo.hint == PROPERTY_HINT_ARRAY_TYPE) {
|
||||
p_method.return_type = p_retinfo.hint_string + "[]";
|
||||
} else if (p_retinfo.type == Variant::DICTIONARY && p_retinfo.hint == PROPERTY_HINT_DICTIONARY_TYPE) {
|
||||
p_method.return_type = "Dictionary[" + p_retinfo.hint_string.replace(";", ", ") + "]";
|
||||
} else if (p_retinfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
|
||||
p_method.return_type = p_retinfo.hint_string;
|
||||
} else if (p_retinfo.type == Variant::NIL && p_retinfo.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
|
||||
@ -93,8 +89,6 @@ void DocData::argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const
|
||||
p_argument.type = p_arginfo.class_name;
|
||||
} else if (p_arginfo.type == Variant::ARRAY && p_arginfo.hint == PROPERTY_HINT_ARRAY_TYPE) {
|
||||
p_argument.type = p_arginfo.hint_string + "[]";
|
||||
} else if (p_arginfo.type == Variant::DICTIONARY && p_arginfo.hint == PROPERTY_HINT_DICTIONARY_TYPE) {
|
||||
p_argument.type = "Dictionary[" + p_arginfo.hint_string.replace(";", ", ") + "]";
|
||||
} else if (p_arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
|
||||
p_argument.type = p_arginfo.hint_string;
|
||||
} else if (p_arginfo.type == Variant::NIL) {
|
||||
|
@ -522,10 +522,6 @@ public:
|
||||
String type;
|
||||
String data_type;
|
||||
String description;
|
||||
bool is_deprecated = false;
|
||||
String deprecated_message;
|
||||
bool is_experimental = false;
|
||||
String experimental_message;
|
||||
String default_value;
|
||||
String keywords;
|
||||
bool operator<(const ThemeItemDoc &p_theme_item) const {
|
||||
@ -554,16 +550,6 @@ public:
|
||||
doc.description = p_dict["description"];
|
||||
}
|
||||
|
||||
if (p_dict.has("deprecated")) {
|
||||
doc.is_deprecated = true;
|
||||
doc.deprecated_message = p_dict["deprecated"];
|
||||
}
|
||||
|
||||
if (p_dict.has("experimental")) {
|
||||
doc.is_experimental = true;
|
||||
doc.experimental_message = p_dict["experimental"];
|
||||
}
|
||||
|
||||
if (p_dict.has("default_value")) {
|
||||
doc.default_value = p_dict["default_value"];
|
||||
}
|
||||
@ -593,14 +579,6 @@ public:
|
||||
dict["description"] = p_doc.description;
|
||||
}
|
||||
|
||||
if (p_doc.is_deprecated) {
|
||||
dict["deprecated"] = p_doc.deprecated_message;
|
||||
}
|
||||
|
||||
if (p_doc.is_experimental) {
|
||||
dict["experimental"] = p_doc.experimental_message;
|
||||
}
|
||||
|
||||
if (!p_doc.default_value.is_empty()) {
|
||||
dict["default_value"] = p_doc.default_value;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
@ -41,7 +41,6 @@
|
||||
* - Are added to the Error enum in core/error/error_list.h
|
||||
* - Have a description added to error_names in core/error/error_list.cpp
|
||||
* - Are bound with BIND_CORE_ENUM_CONSTANT() in core/core_constants.cpp
|
||||
* - Have a matching Android version in platform/android/java/lib/src/org/godotengine/godot/error/Error.kt
|
||||
*/
|
||||
|
||||
enum Error {
|
||||
|
@ -34,12 +34,6 @@
|
||||
#include "core/os/os.h"
|
||||
#include "core/string/ustring.h"
|
||||
|
||||
// Optional physics interpolation warnings try to include the path to the relevant node.
|
||||
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
|
||||
#include "core/config/project_settings.h"
|
||||
#include "scene/main/node.h"
|
||||
#endif
|
||||
|
||||
static ErrorHandlerList *error_handler_list = nullptr;
|
||||
|
||||
void add_error_handler(ErrorHandlerList *p_handler) {
|
||||
@ -134,48 +128,3 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
|
||||
void _err_flush_stdout() {
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
// Prevent error spam by limiting the warnings to a certain frequency.
|
||||
void _physics_interpolation_warning(const char *p_function, const char *p_file, int p_line, ObjectID p_id, const char *p_warn_string) {
|
||||
#if defined(DEBUG_ENABLED) && defined(TOOLS_ENABLED)
|
||||
const uint32_t warn_max = 2048;
|
||||
const uint32_t warn_timeout_seconds = 15;
|
||||
|
||||
static uint32_t warn_count = warn_max;
|
||||
static uint32_t warn_timeout = warn_timeout_seconds;
|
||||
|
||||
uint32_t time_now = UINT32_MAX;
|
||||
|
||||
if (warn_count) {
|
||||
warn_count--;
|
||||
}
|
||||
|
||||
if (!warn_count) {
|
||||
time_now = OS::get_singleton()->get_ticks_msec() / 1000;
|
||||
}
|
||||
|
||||
if ((warn_count == 0) && (time_now >= warn_timeout)) {
|
||||
warn_count = warn_max;
|
||||
warn_timeout = time_now + warn_timeout_seconds;
|
||||
|
||||
if (GLOBAL_GET("debug/settings/physics_interpolation/enable_warnings")) {
|
||||
// UINT64_MAX means unused.
|
||||
if (p_id.operator uint64_t() == UINT64_MAX) {
|
||||
_err_print_error(p_function, p_file, p_line, "[Physics interpolation] " + String(p_warn_string) + " (possibly benign).", false, ERR_HANDLER_WARNING);
|
||||
} else {
|
||||
String node_name;
|
||||
if (p_id.is_valid()) {
|
||||
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(p_id));
|
||||
if (node && node->is_inside_tree()) {
|
||||
node_name = "\"" + String(node->get_path()) + "\"";
|
||||
} else {
|
||||
node_name = "\"unknown\"";
|
||||
}
|
||||
}
|
||||
|
||||
_err_print_error(p_function, p_file, p_line, "[Physics interpolation] " + String(p_warn_string) + ": " + node_name + " (possibly benign).", false, ERR_HANDLER_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -31,7 +31,6 @@
|
||||
#ifndef ERROR_MACROS_H
|
||||
#define ERROR_MACROS_H
|
||||
|
||||
#include "core/object/object_id.h"
|
||||
#include "core/typedefs.h"
|
||||
|
||||
#include <atomic> // We'd normally use safe_refcount.h, but that would cause circular includes.
|
||||
@ -72,8 +71,6 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li
|
||||
void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify = false, bool fatal = false);
|
||||
void _err_flush_stdout();
|
||||
|
||||
void _physics_interpolation_warning(const char *p_function, const char *p_file, int p_line, ObjectID p_id, const char *p_warn_string);
|
||||
|
||||
#ifdef __GNUC__
|
||||
//#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying
|
||||
#define FUNCTION_STR __FUNCTION__
|
||||
@ -835,14 +832,4 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
|
||||
#define DEV_CHECK_ONCE(m_cond)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Physics Interpolation warnings.
|
||||
* These are spam protection warnings.
|
||||
*/
|
||||
#define PHYSICS_INTERPOLATION_NODE_WARNING(m_object_id, m_string) \
|
||||
_physics_interpolation_warning(FUNCTION_STR, __FILE__, __LINE__, m_object_id, m_string)
|
||||
|
||||
#define PHYSICS_INTERPOLATION_WARNING(m_string) \
|
||||
_physics_interpolation_warning(FUNCTION_STR, __FILE__, __LINE__, ObjectID(UINT64_MAX), m_string)
|
||||
|
||||
#endif // ERROR_MACROS_H
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
@ -60,9 +60,6 @@ static String get_property_info_type_name(const PropertyInfo &p_info) {
|
||||
if (p_info.type == Variant::ARRAY && (p_info.hint == PROPERTY_HINT_ARRAY_TYPE)) {
|
||||
return String("typedarray::") + p_info.hint_string;
|
||||
}
|
||||
if (p_info.type == Variant::DICTIONARY && (p_info.hint == PROPERTY_HINT_DICTIONARY_TYPE)) {
|
||||
return String("typeddictionary::") + p_info.hint_string;
|
||||
}
|
||||
if (p_info.type == Variant::INT && (p_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM))) {
|
||||
return String("enum::") + String(p_info.class_name);
|
||||
}
|
||||
@ -88,7 +85,7 @@ static String get_property_info_type_name(const PropertyInfo &p_info) {
|
||||
}
|
||||
|
||||
static String get_type_meta_name(const GodotTypeInfo::Metadata metadata) {
|
||||
static const char *argmeta[13] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double", "char16", "char32" };
|
||||
static const char *argmeta[11] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double" };
|
||||
return argmeta[metadata];
|
||||
}
|
||||
|
||||
@ -1017,7 +1014,6 @@ 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
|
||||
|
@ -32,9 +32,11 @@
|
||||
#include "gdextension.compat.inc"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/io/dir_access.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/object/method_bind.h"
|
||||
#include "gdextension_library_loader.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/version.h"
|
||||
#include "gdextension_manager.h"
|
||||
|
||||
extern void gdextension_setup_interface();
|
||||
@ -46,6 +48,146 @@ String GDExtension::get_extension_list_config_file() {
|
||||
return ProjectSettings::get_singleton()->get_project_data_path().path_join("extension_list.cfg");
|
||||
}
|
||||
|
||||
Vector<SharedObject> GDExtension::find_extension_dependencies(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature) {
|
||||
Vector<SharedObject> dependencies_shared_objects;
|
||||
if (p_config->has_section("dependencies")) {
|
||||
List<String> config_dependencies;
|
||||
p_config->get_section_keys("dependencies", &config_dependencies);
|
||||
|
||||
for (const String &dependency : config_dependencies) {
|
||||
Vector<String> dependency_tags = dependency.split(".");
|
||||
bool all_tags_met = true;
|
||||
for (int i = 0; i < dependency_tags.size(); i++) {
|
||||
String tag = dependency_tags[i].strip_edges();
|
||||
if (!p_has_feature(tag)) {
|
||||
all_tags_met = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_tags_met) {
|
||||
Dictionary dependency_value = p_config->get_value("dependencies", dependency);
|
||||
for (const Variant *key = dependency_value.next(nullptr); key; key = dependency_value.next(key)) {
|
||||
String dependency_path = *key;
|
||||
String target_path = dependency_value[*key];
|
||||
if (dependency_path.is_relative_path()) {
|
||||
dependency_path = p_path.get_base_dir().path_join(dependency_path);
|
||||
}
|
||||
dependencies_shared_objects.push_back(SharedObject(dependency_path, dependency_tags, target_path));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dependencies_shared_objects;
|
||||
}
|
||||
|
||||
String GDExtension::find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags) {
|
||||
// First, check the explicit libraries.
|
||||
if (p_config->has_section("libraries")) {
|
||||
List<String> libraries;
|
||||
p_config->get_section_keys("libraries", &libraries);
|
||||
|
||||
// Iterate the libraries, finding the best matching tags.
|
||||
String best_library_path;
|
||||
Vector<String> best_library_tags;
|
||||
for (const String &E : libraries) {
|
||||
Vector<String> tags = E.split(".");
|
||||
bool all_tags_met = true;
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
String tag = tags[i].strip_edges();
|
||||
if (!p_has_feature(tag)) {
|
||||
all_tags_met = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_tags_met && tags.size() > best_library_tags.size()) {
|
||||
best_library_path = p_config->get_value("libraries", E);
|
||||
best_library_tags = tags;
|
||||
}
|
||||
}
|
||||
|
||||
if (!best_library_path.is_empty()) {
|
||||
if (best_library_path.is_relative_path()) {
|
||||
best_library_path = p_path.get_base_dir().path_join(best_library_path);
|
||||
}
|
||||
if (r_tags != nullptr) {
|
||||
r_tags->append_array(best_library_tags);
|
||||
}
|
||||
return best_library_path;
|
||||
}
|
||||
}
|
||||
|
||||
// Second, try to autodetect
|
||||
String autodetect_library_prefix;
|
||||
if (p_config->has_section_key("configuration", "autodetect_library_prefix")) {
|
||||
autodetect_library_prefix = p_config->get_value("configuration", "autodetect_library_prefix");
|
||||
}
|
||||
if (!autodetect_library_prefix.is_empty()) {
|
||||
String autodetect_path = autodetect_library_prefix;
|
||||
if (autodetect_path.is_relative_path()) {
|
||||
autodetect_path = p_path.get_base_dir().path_join(autodetect_path);
|
||||
}
|
||||
|
||||
// Find the folder and file parts of the prefix.
|
||||
String folder;
|
||||
String file_prefix;
|
||||
if (DirAccess::dir_exists_absolute(autodetect_path)) {
|
||||
folder = autodetect_path;
|
||||
} else if (DirAccess::dir_exists_absolute(autodetect_path.get_base_dir())) {
|
||||
folder = autodetect_path.get_base_dir();
|
||||
file_prefix = autodetect_path.get_file();
|
||||
} else {
|
||||
ERR_FAIL_V_MSG(String(), vformat("Error in extension: %s. Could not find folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix));
|
||||
}
|
||||
|
||||
// Open the folder.
|
||||
Ref<DirAccess> dir = DirAccess::open(folder);
|
||||
ERR_FAIL_COND_V_MSG(!dir.is_valid(), String(), vformat("Error in extension: %s. Could not open folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix));
|
||||
|
||||
// Iterate the files and check the prefixes, finding the best matching file.
|
||||
String best_file;
|
||||
Vector<String> best_file_tags;
|
||||
dir->list_dir_begin();
|
||||
String file_name = dir->_get_next();
|
||||
while (file_name != "") {
|
||||
if (!dir->current_is_dir() && file_name.begins_with(file_prefix)) {
|
||||
// Check if the files matches all requested feature tags.
|
||||
String tags_str = file_name.trim_prefix(file_prefix);
|
||||
tags_str = tags_str.trim_suffix(tags_str.get_extension());
|
||||
|
||||
Vector<String> tags = tags_str.split(".", false);
|
||||
bool all_tags_met = true;
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
String tag = tags[i].strip_edges();
|
||||
if (!p_has_feature(tag)) {
|
||||
all_tags_met = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If all tags are found in the feature list, and we found more tags than before, use this file.
|
||||
if (all_tags_met && tags.size() > best_file_tags.size()) {
|
||||
best_file_tags = tags;
|
||||
best_file = file_name;
|
||||
}
|
||||
}
|
||||
file_name = dir->_get_next();
|
||||
}
|
||||
|
||||
if (!best_file.is_empty()) {
|
||||
String library_path = folder.path_join(best_file);
|
||||
if (r_tags != nullptr) {
|
||||
r_tags->append_array(best_file_tags);
|
||||
}
|
||||
return library_path;
|
||||
}
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
class GDExtensionMethodBind : public MethodBind {
|
||||
GDExtensionClassMethodCall call_func;
|
||||
GDExtensionClassMethodValidatedCall validated_call_func;
|
||||
@ -240,7 +382,7 @@ public:
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs) {
|
||||
const GDExtensionClassCreationInfo4 class_info4 = {
|
||||
const GDExtensionClassCreationInfo3 class_info3 = {
|
||||
p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
|
||||
p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
|
||||
true, // GDExtensionBool is_exposed;
|
||||
@ -256,26 +398,25 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library
|
||||
p_extension_funcs->to_string_func, // GDExtensionClassToString to_string_func;
|
||||
p_extension_funcs->reference_func, // GDExtensionClassReference reference_func;
|
||||
p_extension_funcs->unreference_func, // GDExtensionClassUnreference unreference_func;
|
||||
nullptr, // GDExtensionClassCreateInstance2 create_instance_func; /* this one is mandatory */
|
||||
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
|
||||
p_extension_funcs->free_instance_func, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
|
||||
nullptr, // GDExtensionClassRecreateInstance recreate_instance_func;
|
||||
p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
|
||||
nullptr, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
|
||||
nullptr, // GDExtensionClassCallVirtualWithData call_virtual_func;
|
||||
p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid;
|
||||
p_extension_funcs->class_userdata, // void *class_userdata;
|
||||
};
|
||||
|
||||
const ClassCreationDeprecatedInfo legacy = {
|
||||
p_extension_funcs->notification_func, // GDExtensionClassNotification notification_func;
|
||||
p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func;
|
||||
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func;
|
||||
p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid;
|
||||
};
|
||||
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info4, &legacy);
|
||||
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info3, &legacy);
|
||||
}
|
||||
|
||||
void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs) {
|
||||
const GDExtensionClassCreationInfo4 class_info4 = {
|
||||
const GDExtensionClassCreationInfo3 class_info3 = {
|
||||
p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
|
||||
p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
|
||||
p_extension_funcs->is_exposed, // GDExtensionBool is_exposed;
|
||||
@ -291,71 +432,34 @@ void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_librar
|
||||
p_extension_funcs->to_string_func, // GDExtensionClassToString to_string_func;
|
||||
p_extension_funcs->reference_func, // GDExtensionClassReference reference_func;
|
||||
p_extension_funcs->unreference_func, // GDExtensionClassUnreference unreference_func;
|
||||
nullptr, // GDExtensionClassCreateInstance2 create_instance_func; /* this one is mandatory */
|
||||
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */
|
||||
p_extension_funcs->free_instance_func, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
|
||||
p_extension_funcs->recreate_instance_func, // GDExtensionClassRecreateInstance recreate_instance_func;
|
||||
p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
|
||||
p_extension_funcs->get_virtual_call_data_func, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
|
||||
p_extension_funcs->call_virtual_with_data_func, // GDExtensionClassCallVirtualWithData call_virtual_func;
|
||||
p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid;
|
||||
p_extension_funcs->class_userdata, // void *class_userdata;
|
||||
};
|
||||
|
||||
const ClassCreationDeprecatedInfo legacy = {
|
||||
nullptr, // GDExtensionClassNotification notification_func;
|
||||
p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func;
|
||||
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func;
|
||||
p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid;
|
||||
};
|
||||
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info4, &legacy);
|
||||
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info3, &legacy);
|
||||
}
|
||||
|
||||
void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs) {
|
||||
const GDExtensionClassCreationInfo4 class_info4 = {
|
||||
p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
|
||||
p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
|
||||
p_extension_funcs->is_exposed, // GDExtensionBool is_exposed;
|
||||
p_extension_funcs->is_runtime, // GDExtensionBool is_runtime;
|
||||
p_extension_funcs->set_func, // GDExtensionClassSet set_func;
|
||||
p_extension_funcs->get_func, // GDExtensionClassGet get_func;
|
||||
p_extension_funcs->get_property_list_func, // GDExtensionClassGetPropertyList get_property_list_func;
|
||||
p_extension_funcs->free_property_list_func, // GDExtensionClassFreePropertyList free_property_list_func;
|
||||
p_extension_funcs->property_can_revert_func, // GDExtensionClassPropertyCanRevert property_can_revert_func;
|
||||
p_extension_funcs->property_get_revert_func, // GDExtensionClassPropertyGetRevert property_get_revert_func;
|
||||
p_extension_funcs->validate_property_func, // GDExtensionClassValidateProperty validate_property_func;
|
||||
p_extension_funcs->notification_func, // GDExtensionClassNotification2 notification_func;
|
||||
p_extension_funcs->to_string_func, // GDExtensionClassToString to_string_func;
|
||||
p_extension_funcs->reference_func, // GDExtensionClassReference reference_func;
|
||||
p_extension_funcs->unreference_func, // GDExtensionClassUnreference unreference_func;
|
||||
nullptr, // GDExtensionClassCreateInstance2 create_instance_func; /* this one is mandatory */
|
||||
p_extension_funcs->free_instance_func, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */
|
||||
p_extension_funcs->recreate_instance_func, // GDExtensionClassRecreateInstance recreate_instance_func;
|
||||
p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
|
||||
p_extension_funcs->get_virtual_call_data_func, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
|
||||
p_extension_funcs->call_virtual_with_data_func, // GDExtensionClassCallVirtualWithData call_virtual_func;
|
||||
p_extension_funcs->class_userdata, // void *class_userdata;
|
||||
};
|
||||
|
||||
const ClassCreationDeprecatedInfo legacy = {
|
||||
nullptr, // GDExtensionClassNotification notification_func;
|
||||
nullptr, // GDExtensionClassFreePropertyList free_property_list_func;
|
||||
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance2 create_instance_func;
|
||||
p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid;
|
||||
};
|
||||
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info4, &legacy);
|
||||
}
|
||||
|
||||
#endif // DISABLE_DEPRECATED
|
||||
|
||||
void GDExtension::_register_extension_class4(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs) {
|
||||
void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs) {
|
||||
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, p_extension_funcs);
|
||||
}
|
||||
|
||||
void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs) {
|
||||
void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs) {
|
||||
GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
|
||||
|
||||
StringName class_name = *reinterpret_cast<const StringName *>(p_class_name);
|
||||
StringName parent_class_name = *reinterpret_cast<const StringName *>(p_parent_class_name);
|
||||
ERR_FAIL_COND_MSG(!String(class_name).is_valid_unicode_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier.");
|
||||
ERR_FAIL_COND_MSG(!String(class_name).is_valid_identifier(), "Attempt to register extension class '" + class_name + "', which is not a valid class identifier.");
|
||||
ERR_FAIL_COND_MSG(ClassDB::class_exists(class_name), "Attempt to register extension class '" + class_name + "', which appears to be already registered.");
|
||||
|
||||
Extension *parent_extension = nullptr;
|
||||
@ -426,8 +530,6 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr
|
||||
if (p_deprecated_funcs) {
|
||||
extension->gdextension.notification = p_deprecated_funcs->notification_func;
|
||||
extension->gdextension.free_property_list = p_deprecated_funcs->free_property_list_func;
|
||||
extension->gdextension.create_instance = p_deprecated_funcs->create_instance_func;
|
||||
extension->gdextension.get_rid = p_deprecated_funcs->get_rid_func;
|
||||
}
|
||||
#endif // DISABLE_DEPRECATED
|
||||
extension->gdextension.notification2 = p_extension_funcs->notification_func;
|
||||
@ -435,12 +537,13 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr
|
||||
extension->gdextension.reference = p_extension_funcs->reference_func;
|
||||
extension->gdextension.unreference = p_extension_funcs->unreference_func;
|
||||
extension->gdextension.class_userdata = p_extension_funcs->class_userdata;
|
||||
extension->gdextension.create_instance2 = p_extension_funcs->create_instance_func;
|
||||
extension->gdextension.create_instance = p_extension_funcs->create_instance_func;
|
||||
extension->gdextension.free_instance = p_extension_funcs->free_instance_func;
|
||||
extension->gdextension.recreate_instance = p_extension_funcs->recreate_instance_func;
|
||||
extension->gdextension.get_virtual = p_extension_funcs->get_virtual_func;
|
||||
extension->gdextension.get_virtual_call_data = p_extension_funcs->get_virtual_call_data_func;
|
||||
extension->gdextension.call_virtual_with_data = p_extension_funcs->call_virtual_with_data_func;
|
||||
extension->gdextension.get_rid = p_extension_funcs->get_rid_func;
|
||||
|
||||
extension->gdextension.reloadable = self->reloadable;
|
||||
#ifdef TOOLS_ENABLED
|
||||
@ -652,13 +755,7 @@ void GDExtension::_unregister_extension_class(GDExtensionClassLibraryPtr p_libra
|
||||
void GDExtension::_get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionUninitializedStringPtr r_path) {
|
||||
GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
|
||||
|
||||
Ref<GDExtensionLibraryLoader> library_loader = self->loader;
|
||||
String library_path;
|
||||
if (library_loader.is_valid()) {
|
||||
library_path = library_loader->library_path;
|
||||
}
|
||||
|
||||
memnew_placement(r_path, String(library_path));
|
||||
memnew_placement(r_path, String(self->library_path));
|
||||
}
|
||||
|
||||
HashMap<StringName, GDExtensionInterfaceFunctionPtr> GDExtension::gdextension_interface_functions;
|
||||
@ -674,32 +771,55 @@ GDExtensionInterfaceFunctionPtr GDExtension::get_interface_function(const String
|
||||
return *function;
|
||||
}
|
||||
|
||||
Error GDExtension::open_library(const String &p_path, const Ref<GDExtensionLoader> &p_loader) {
|
||||
ERR_FAIL_COND_V_MSG(p_loader.is_null(), FAILED, "Can't open GDExtension without a loader.");
|
||||
loader = p_loader;
|
||||
Error GDExtension::open_library(const String &p_path, const String &p_entry_symbol, Vector<SharedObject> *p_dependencies) {
|
||||
String abs_path = ProjectSettings::get_singleton()->globalize_path(p_path);
|
||||
|
||||
Error err = loader->open_library(p_path);
|
||||
Vector<String> abs_dependencies_paths;
|
||||
if (p_dependencies != nullptr && !p_dependencies->is_empty()) {
|
||||
for (const SharedObject &dependency : *p_dependencies) {
|
||||
abs_dependencies_paths.push_back(ProjectSettings::get_singleton()->globalize_path(dependency.path));
|
||||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_V_MSG(err == ERR_FILE_NOT_FOUND, err, "GDExtension dynamic library not found: " + p_path);
|
||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Can't open GDExtension dynamic library: " + p_path);
|
||||
OS::GDExtensionData data = {
|
||||
true, // also_set_library_path
|
||||
&library_path, // r_resolved_path
|
||||
Engine::get_singleton()->is_editor_hint(), // generate_temp_files
|
||||
&abs_dependencies_paths, // library_dependencies
|
||||
};
|
||||
Error err = OS::get_singleton()->open_dynamic_library(abs_path, library, &data);
|
||||
|
||||
err = loader->initialize(&gdextension_get_proc_address, this, &initialization);
|
||||
ERR_FAIL_COND_V_MSG(err == ERR_FILE_NOT_FOUND, err, "GDExtension dynamic library not found: " + abs_path);
|
||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Can't open GDExtension dynamic library: " + abs_path);
|
||||
|
||||
void *entry_funcptr = nullptr;
|
||||
|
||||
err = OS::get_singleton()->get_dynamic_library_symbol_handle(library, p_entry_symbol, entry_funcptr, false);
|
||||
|
||||
if (err != OK) {
|
||||
// Errors already logged in initialize().
|
||||
loader->close_library();
|
||||
ERR_PRINT("GDExtension entry point '" + p_entry_symbol + "' not found in library " + abs_path);
|
||||
OS::get_singleton()->close_dynamic_library(library);
|
||||
return err;
|
||||
}
|
||||
|
||||
level_initialized = -1;
|
||||
GDExtensionInitializationFunction initialization_function = (GDExtensionInitializationFunction)entry_funcptr;
|
||||
GDExtensionBool ret = initialization_function(&gdextension_get_proc_address, this, &initialization);
|
||||
|
||||
return OK;
|
||||
if (ret) {
|
||||
level_initialized = -1;
|
||||
return OK;
|
||||
} else {
|
||||
ERR_PRINT("GDExtension initialization function '" + p_entry_symbol + "' returned an error.");
|
||||
OS::get_singleton()->close_dynamic_library(library);
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
void GDExtension::close_library() {
|
||||
ERR_FAIL_COND(!is_library_open());
|
||||
loader->close_library();
|
||||
ERR_FAIL_NULL(library);
|
||||
OS::get_singleton()->close_dynamic_library(library);
|
||||
|
||||
library = nullptr;
|
||||
class_icon_paths.clear();
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
@ -708,16 +828,16 @@ void GDExtension::close_library() {
|
||||
}
|
||||
|
||||
bool GDExtension::is_library_open() const {
|
||||
return loader.is_valid() && loader->is_library_open();
|
||||
return library != nullptr;
|
||||
}
|
||||
|
||||
GDExtension::InitializationLevel GDExtension::get_minimum_library_initialization_level() const {
|
||||
ERR_FAIL_COND_V(!is_library_open(), INITIALIZATION_LEVEL_CORE);
|
||||
ERR_FAIL_NULL_V(library, INITIALIZATION_LEVEL_CORE);
|
||||
return InitializationLevel(initialization.minimum_initialization_level);
|
||||
}
|
||||
|
||||
void GDExtension::initialize_library(InitializationLevel p_level) {
|
||||
ERR_FAIL_COND(!is_library_open());
|
||||
ERR_FAIL_NULL(library);
|
||||
ERR_FAIL_COND_MSG(p_level <= int32_t(level_initialized), vformat("Level '%d' must be higher than the current level '%d'", p_level, level_initialized));
|
||||
|
||||
level_initialized = int32_t(p_level);
|
||||
@ -727,7 +847,7 @@ void GDExtension::initialize_library(InitializationLevel p_level) {
|
||||
initialization.initialize(initialization.userdata, GDExtensionInitializationLevel(p_level));
|
||||
}
|
||||
void GDExtension::deinitialize_library(InitializationLevel p_level) {
|
||||
ERR_FAIL_COND(!is_library_open());
|
||||
ERR_FAIL_NULL(library);
|
||||
ERR_FAIL_COND(p_level > int32_t(level_initialized));
|
||||
|
||||
level_initialized = int32_t(p_level) - 1;
|
||||
@ -751,7 +871,7 @@ GDExtension::GDExtension() {
|
||||
}
|
||||
|
||||
GDExtension::~GDExtension() {
|
||||
if (is_library_open()) {
|
||||
if (library != nullptr) {
|
||||
close_library();
|
||||
}
|
||||
#ifdef TOOLS_ENABLED
|
||||
@ -768,9 +888,8 @@ void GDExtension::initialize_gdextensions() {
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
register_interface_function("classdb_register_extension_class", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class);
|
||||
register_interface_function("classdb_register_extension_class2", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class2);
|
||||
register_interface_function("classdb_register_extension_class3", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class3);
|
||||
#endif // DISABLE_DEPRECATED
|
||||
register_interface_function("classdb_register_extension_class4", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class4);
|
||||
register_interface_function("classdb_register_extension_class3", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class3);
|
||||
register_interface_function("classdb_register_extension_class_method", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_method);
|
||||
register_interface_function("classdb_register_extension_class_virtual_method", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_virtual_method);
|
||||
register_interface_function("classdb_register_extension_class_integer_constant", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class_integer_constant);
|
||||
@ -790,15 +909,142 @@ void GDExtension::finalize_gdextensions() {
|
||||
Error GDExtensionResourceLoader::load_gdextension_resource(const String &p_path, Ref<GDExtension> &p_extension) {
|
||||
ERR_FAIL_COND_V_MSG(p_extension.is_valid() && p_extension->is_library_open(), ERR_ALREADY_IN_USE, "Cannot load GDExtension resource into already opened library.");
|
||||
|
||||
GDExtensionManager *extension_manager = GDExtensionManager::get_singleton();
|
||||
Ref<ConfigFile> config;
|
||||
config.instantiate();
|
||||
|
||||
GDExtensionManager::LoadStatus status = extension_manager->load_extension(p_path);
|
||||
if (status != GDExtensionManager::LOAD_STATUS_OK && status != GDExtensionManager::LOAD_STATUS_ALREADY_LOADED) {
|
||||
// Errors already logged in load_extension().
|
||||
return FAILED;
|
||||
Error err = config->load(p_path);
|
||||
|
||||
if (err != OK) {
|
||||
ERR_PRINT("Error loading GDExtension configuration file: " + p_path);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!config->has_section_key("configuration", "entry_symbol")) {
|
||||
ERR_PRINT("GDExtension configuration file must contain a \"configuration/entry_symbol\" key: " + p_path);
|
||||
return ERR_INVALID_DATA;
|
||||
}
|
||||
|
||||
String entry_symbol = config->get_value("configuration", "entry_symbol");
|
||||
|
||||
uint32_t compatibility_minimum[3] = { 0, 0, 0 };
|
||||
if (config->has_section_key("configuration", "compatibility_minimum")) {
|
||||
String compat_string = config->get_value("configuration", "compatibility_minimum");
|
||||
Vector<int> parts = compat_string.split_ints(".");
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
if (i >= 3) {
|
||||
break;
|
||||
}
|
||||
if (parts[i] >= 0) {
|
||||
compatibility_minimum[i] = parts[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ERR_PRINT("GDExtension configuration file must contain a \"configuration/compatibility_minimum\" key: " + p_path);
|
||||
return ERR_INVALID_DATA;
|
||||
}
|
||||
|
||||
if (compatibility_minimum[0] < 4 || (compatibility_minimum[0] == 4 && compatibility_minimum[1] == 0)) {
|
||||
ERR_PRINT(vformat("GDExtension's compatibility_minimum (%d.%d.%d) must be at least 4.1.0: %s", compatibility_minimum[0], compatibility_minimum[1], compatibility_minimum[2], p_path));
|
||||
return ERR_INVALID_DATA;
|
||||
}
|
||||
|
||||
bool compatible = true;
|
||||
// Check version lexicographically.
|
||||
if (VERSION_MAJOR != compatibility_minimum[0]) {
|
||||
compatible = VERSION_MAJOR > compatibility_minimum[0];
|
||||
} else if (VERSION_MINOR != compatibility_minimum[1]) {
|
||||
compatible = VERSION_MINOR > compatibility_minimum[1];
|
||||
} else {
|
||||
compatible = VERSION_PATCH >= compatibility_minimum[2];
|
||||
}
|
||||
if (!compatible) {
|
||||
ERR_PRINT(vformat("GDExtension only compatible with Godot version %d.%d.%d or later: %s", compatibility_minimum[0], compatibility_minimum[1], compatibility_minimum[2], p_path));
|
||||
return ERR_INVALID_DATA;
|
||||
}
|
||||
|
||||
// Optionally check maximum compatibility.
|
||||
if (config->has_section_key("configuration", "compatibility_maximum")) {
|
||||
uint32_t compatibility_maximum[3] = { 0, 0, 0 };
|
||||
String compat_string = config->get_value("configuration", "compatibility_maximum");
|
||||
Vector<int> parts = compat_string.split_ints(".");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (i < parts.size() && parts[i] >= 0) {
|
||||
compatibility_maximum[i] = parts[i];
|
||||
} else {
|
||||
// If a version part is missing, set the maximum to an arbitrary high value.
|
||||
compatibility_maximum[i] = 9999;
|
||||
}
|
||||
}
|
||||
|
||||
compatible = true;
|
||||
if (VERSION_MAJOR != compatibility_maximum[0]) {
|
||||
compatible = VERSION_MAJOR < compatibility_maximum[0];
|
||||
} else if (VERSION_MINOR != compatibility_maximum[1]) {
|
||||
compatible = VERSION_MINOR < compatibility_maximum[1];
|
||||
}
|
||||
#if VERSION_PATCH
|
||||
// #if check to avoid -Wtype-limits warning when 0.
|
||||
else {
|
||||
compatible = VERSION_PATCH <= compatibility_maximum[2];
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!compatible) {
|
||||
ERR_PRINT(vformat("GDExtension only compatible with Godot version %s or earlier: %s", compat_string, p_path));
|
||||
return ERR_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
String library_path = GDExtension::find_extension_library(p_path, config, [](const String &p_feature) { return OS::get_singleton()->has_feature(p_feature); });
|
||||
|
||||
if (library_path.is_empty()) {
|
||||
const String os_arch = OS::get_singleton()->get_name().to_lower() + "." + Engine::get_singleton()->get_architecture_name();
|
||||
ERR_PRINT(vformat("No GDExtension library found for current OS and architecture (%s) in configuration file: %s", os_arch, p_path));
|
||||
return ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
bool is_static_library = library_path.ends_with(".a") || library_path.ends_with(".xcframework");
|
||||
|
||||
if (!library_path.is_resource_file() && !library_path.is_absolute_path()) {
|
||||
library_path = p_path.get_base_dir().path_join(library_path);
|
||||
}
|
||||
|
||||
if (p_extension.is_null()) {
|
||||
p_extension.instantiate();
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
p_extension->set_reloadable(config->get_value("configuration", "reloadable", false) && Engine::get_singleton()->is_extension_reloading_enabled());
|
||||
|
||||
p_extension->update_last_modified_time(
|
||||
FileAccess::get_modified_time(p_path),
|
||||
FileAccess::get_modified_time(library_path));
|
||||
#endif
|
||||
|
||||
Vector<SharedObject> library_dependencies = GDExtension::find_extension_dependencies(p_path, config, [](const String &p_feature) { return OS::get_singleton()->has_feature(p_feature); });
|
||||
err = p_extension->open_library(is_static_library ? String() : library_path, entry_symbol, &library_dependencies);
|
||||
if (err != OK) {
|
||||
// Unreference the extension so that this loading can be considered a failure.
|
||||
p_extension.unref();
|
||||
|
||||
// Errors already logged in open_library()
|
||||
return err;
|
||||
}
|
||||
|
||||
// Handle icons if any are specified.
|
||||
if (config->has_section("icons")) {
|
||||
List<String> keys;
|
||||
config->get_section_keys("icons", &keys);
|
||||
for (const String &key : keys) {
|
||||
String icon_path = config->get_value("icons", key);
|
||||
if (icon_path.is_relative_path()) {
|
||||
icon_path = p_path.get_base_dir().path_join(icon_path);
|
||||
}
|
||||
|
||||
p_extension->class_icon_paths[key] = icon_path;
|
||||
}
|
||||
}
|
||||
|
||||
p_extension = extension_manager->get_extension(p_path);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -839,7 +1085,16 @@ String GDExtensionResourceLoader::get_resource_type(const String &p_path) const
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
bool GDExtension::has_library_changed() const {
|
||||
return loader->has_library_changed();
|
||||
// Check only that the last modified time is different (rather than checking
|
||||
// that it's newer) since some OS's (namely Windows) will preserve the modified
|
||||
// time by default when copying files.
|
||||
if (FileAccess::get_modified_time(get_path()) != resource_last_modified_time) {
|
||||
return true;
|
||||
}
|
||||
if (FileAccess::get_modified_time(library_path) != library_last_modified_time) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GDExtension::prepare_reload() {
|
||||
|
@ -31,11 +31,13 @@
|
||||
#ifndef GDEXTENSION_H
|
||||
#define GDEXTENSION_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "core/extension/gdextension_interface.h"
|
||||
#include "core/extension/gdextension_loader.h"
|
||||
#include "core/io/config_file.h"
|
||||
#include "core/io/resource_loader.h"
|
||||
#include "core/object/ref_counted.h"
|
||||
#include "core/os/shared_object.h"
|
||||
|
||||
class GDExtensionMethodBind;
|
||||
|
||||
@ -44,8 +46,8 @@ class GDExtension : public Resource {
|
||||
|
||||
friend class GDExtensionManager;
|
||||
|
||||
Ref<GDExtensionLoader> loader;
|
||||
|
||||
void *library = nullptr; // pointer if valid,
|
||||
String library_path;
|
||||
bool reloadable = false;
|
||||
|
||||
struct Extension {
|
||||
@ -70,18 +72,15 @@ class GDExtension : public Resource {
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
GDExtensionClassNotification notification_func = nullptr;
|
||||
GDExtensionClassFreePropertyList free_property_list_func = nullptr;
|
||||
GDExtensionClassCreateInstance create_instance_func = nullptr;
|
||||
GDExtensionClassGetRID get_rid_func = nullptr;
|
||||
#endif // DISABLE_DEPRECATED
|
||||
};
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
static void _register_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo *p_extension_funcs);
|
||||
static void _register_extension_class2(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs);
|
||||
static void _register_extension_class3(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs);
|
||||
#endif // DISABLE_DEPRECATED
|
||||
static void _register_extension_class4(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs);
|
||||
static void _register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs = nullptr);
|
||||
static void _register_extension_class3(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs);
|
||||
static void _register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs = nullptr);
|
||||
static void _register_extension_class_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassMethodInfo *p_method_info);
|
||||
static void _register_extension_class_virtual_method(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, const GDExtensionClassVirtualMethodInfo *p_method_info);
|
||||
static void _register_extension_class_integer_constant(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_enum_name, GDExtensionConstStringNamePtr p_constant_name, GDExtensionInt p_constant_value, GDExtensionBool p_is_bitfield);
|
||||
@ -97,6 +96,8 @@ class GDExtension : public Resource {
|
||||
int32_t level_initialized = -1;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
uint64_t resource_last_modified_time = 0;
|
||||
uint64_t library_last_modified_time = 0;
|
||||
bool is_reloading = false;
|
||||
Vector<GDExtensionMethodBind *> invalid_methods;
|
||||
Vector<ObjectID> instance_bindings;
|
||||
@ -123,12 +124,11 @@ public:
|
||||
virtual bool editor_can_reload_from_file() override { return false; } // Reloading is handled in a special way.
|
||||
|
||||
static String get_extension_list_config_file();
|
||||
static String find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags = nullptr);
|
||||
static Vector<SharedObject> find_extension_dependencies(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature);
|
||||
|
||||
const Ref<GDExtensionLoader> get_loader() const { return loader; }
|
||||
|
||||
Error open_library(const String &p_path, const Ref<GDExtensionLoader> &p_loader);
|
||||
Error open_library(const String &p_path, const String &p_entry_symbol, Vector<SharedObject> *p_dependencies = nullptr);
|
||||
void close_library();
|
||||
bool is_library_open() const;
|
||||
|
||||
enum InitializationLevel {
|
||||
INITIALIZATION_LEVEL_CORE = GDEXTENSION_INITIALIZATION_CORE,
|
||||
@ -146,11 +146,17 @@ protected:
|
||||
#endif
|
||||
|
||||
public:
|
||||
bool is_library_open() const;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
bool is_reloadable() const { return reloadable; }
|
||||
void set_reloadable(bool p_reloadable) { reloadable = p_reloadable; }
|
||||
|
||||
bool has_library_changed() const;
|
||||
void update_last_modified_time(uint64_t p_resource_last_modified_time, uint64_t p_library_last_modified_time) {
|
||||
resource_last_modified_time = p_resource_last_modified_time;
|
||||
library_last_modified_time = p_library_last_modified_time;
|
||||
}
|
||||
|
||||
void track_instance_binding(Object *p_object);
|
||||
void untrack_instance_binding(Object *p_object);
|
||||
|
@ -103,14 +103,6 @@ void GDExtensionCompatHashes::initialize() {
|
||||
mappings.insert("AcceptDialog", {
|
||||
{ "add_button", 4158837846, 3328440682 },
|
||||
});
|
||||
mappings.insert("AnimatedSprite2D", {
|
||||
{ "play", 2372066587, 3269405555 },
|
||||
{ "play_backwards", 1421762485, 3323268493 },
|
||||
});
|
||||
mappings.insert("AnimatedSprite3D", {
|
||||
{ "play", 2372066587, 3269405555 },
|
||||
{ "play_backwards", 1421762485, 3323268493 },
|
||||
});
|
||||
mappings.insert("Animation", {
|
||||
{ "add_track", 2393815928, 3843682357 },
|
||||
{ "track_insert_key", 1985425300, 808952278 },
|
||||
@ -154,12 +146,6 @@ void GDExtensionCompatHashes::initialize() {
|
||||
{ "travel", 3683006648, 3823612587 },
|
||||
{ "start", 3683006648, 3823612587 },
|
||||
});
|
||||
mappings.insert("AnimationPlayer", {
|
||||
{ "play", 3697947785, 3118260607 },
|
||||
{ "play", 2221377757, 3118260607 },
|
||||
{ "play_backwards", 3890664824, 2787282401 },
|
||||
{ "play_with_capture", 3180464118, 1572969103 },
|
||||
});
|
||||
mappings.insert("ArrayMesh", {
|
||||
{ "add_surface_from_arrays", 172284304, 1796411378 },
|
||||
});
|
||||
@ -261,20 +247,13 @@ void GDExtensionCompatHashes::initialize() {
|
||||
});
|
||||
mappings.insert("DisplayServer", {
|
||||
{ "global_menu_add_submenu_item", 3806306913, 2828985934 },
|
||||
{ "global_menu_add_item", 3415468211, 3616842746 },
|
||||
{ "global_menu_add_item", 3401266716, 3616842746 },
|
||||
{ "global_menu_add_check_item", 3415468211, 3616842746 },
|
||||
{ "global_menu_add_check_item", 3401266716, 3616842746 },
|
||||
{ "global_menu_add_icon_item", 1700867534, 3867083847 },
|
||||
{ "global_menu_add_icon_item", 4245856523, 3867083847 },
|
||||
{ "global_menu_add_icon_check_item", 1700867534, 3867083847 },
|
||||
{ "global_menu_add_icon_check_item", 4245856523, 3867083847 },
|
||||
{ "global_menu_add_radio_check_item", 3415468211, 3616842746 },
|
||||
{ "global_menu_add_radio_check_item", 3401266716, 3616842746 },
|
||||
{ "global_menu_add_icon_radio_check_item", 1700867534, 3867083847 },
|
||||
{ "global_menu_add_icon_radio_check_item", 4245856523, 3867083847 },
|
||||
{ "global_menu_add_multistate_item", 635750054, 3297554655 },
|
||||
{ "global_menu_add_multistate_item", 3431222859, 3297554655 },
|
||||
{ "global_menu_add_item", 3415468211, 3401266716 },
|
||||
{ "global_menu_add_check_item", 3415468211, 3401266716 },
|
||||
{ "global_menu_add_icon_item", 1700867534, 4245856523 },
|
||||
{ "global_menu_add_icon_check_item", 1700867534, 4245856523 },
|
||||
{ "global_menu_add_radio_check_item", 3415468211, 3401266716 },
|
||||
{ "global_menu_add_icon_radio_check_item", 1700867534, 4245856523 },
|
||||
{ "global_menu_add_multistate_item", 635750054, 3431222859 },
|
||||
{ "global_menu_add_separator", 1041533178, 3214812433 },
|
||||
{ "tts_speak", 3741216677, 903992738 },
|
||||
{ "is_touchscreen_available", 4162880507, 3323674545 },
|
||||
@ -307,12 +286,6 @@ void GDExtensionCompatHashes::initialize() {
|
||||
{ "virtual_keyboard_show", 860410478, 3042891259 },
|
||||
#endif
|
||||
});
|
||||
mappings.insert("EditorExportPlatform", {
|
||||
{ "export_project_files", 425454869, 1063735070 },
|
||||
});
|
||||
mappings.insert("EditorProperty", {
|
||||
{ "emit_changed", 3069422438, 1822500399 },
|
||||
});
|
||||
mappings.insert("ENetConnection", {
|
||||
{ "create_host_bound", 866250949, 1515002313 },
|
||||
{ "connect_to_host", 385984708, 2171300490 },
|
||||
@ -480,35 +453,18 @@ void GDExtensionCompatHashes::initialize() {
|
||||
mappings.insert("MultiplayerAPI", {
|
||||
{ "rpc", 1833408346, 2077486355 },
|
||||
});
|
||||
mappings.insert("NativeMenu", {
|
||||
{ "add_item", 2553375659, 980552939 },
|
||||
{ "add_check_item", 2553375659, 980552939 },
|
||||
{ "add_icon_item", 2987595282, 1372188274 },
|
||||
{ "add_icon_check_item", 2987595282, 1372188274 },
|
||||
{ "add_radio_check_item", 2553375659, 980552939 },
|
||||
{ "add_icon_radio_check_item", 2987595282, 1372188274 },
|
||||
{ "add_multistate_item", 1558592568, 2674635658 },
|
||||
});
|
||||
mappings.insert("NavigationMeshGenerator", {
|
||||
{ "parse_source_geometry_data", 3703028813, 3172802542 },
|
||||
{ "parse_source_geometry_data", 685862123, 3172802542 },
|
||||
{ "bake_from_source_geometry_data", 3669016597, 1286748856 },
|
||||
{ "bake_from_source_geometry_data", 2469318639, 1286748856 },
|
||||
{ "parse_source_geometry_data", 3703028813, 685862123 },
|
||||
{ "bake_from_source_geometry_data", 3669016597, 2469318639 },
|
||||
});
|
||||
mappings.insert("NavigationServer2D", {
|
||||
{ "map_get_path", 56240621, 3146466012 },
|
||||
{ "parse_source_geometry_data", 1176164995, 1766905497 },
|
||||
{ "bake_from_source_geometry_data", 2909414286, 2179660022 },
|
||||
{ "bake_from_source_geometry_data_async", 2909414286, 2179660022 },
|
||||
});
|
||||
mappings.insert("NavigationServer3D", {
|
||||
{ "map_get_path", 2121045993, 1187418690 },
|
||||
{ "parse_source_geometry_data", 3703028813, 3172802542 },
|
||||
{ "parse_source_geometry_data", 685862123, 3172802542 },
|
||||
{ "bake_from_source_geometry_data", 3669016597, 1286748856 },
|
||||
{ "bake_from_source_geometry_data", 2469318639, 1286748856 },
|
||||
{ "bake_from_source_geometry_data_async", 3669016597, 1286748856 },
|
||||
{ "bake_from_source_geometry_data_async", 2469318639, 1286748856 },
|
||||
{ "parse_source_geometry_data", 3703028813, 685862123 },
|
||||
{ "bake_from_source_geometry_data", 3669016597, 2469318639 },
|
||||
{ "bake_from_source_geometry_data_async", 3669016597, 2469318639 },
|
||||
});
|
||||
mappings.insert("Node", {
|
||||
{ "add_child", 3070154285, 3863233950 },
|
||||
@ -675,11 +631,6 @@ void GDExtensionCompatHashes::initialize() {
|
||||
mappings.insert("ProjectSettings", {
|
||||
{ "load_resource_pack", 3001721055, 708980503 },
|
||||
});
|
||||
mappings.insert("RDShaderFile", {
|
||||
{ "bake_from_source_geometry_data_async", 2469318639, 1286748856 },
|
||||
{ "set_bytecode", 1558064255, 1526857008 },
|
||||
{ "get_spirv", 3340165340, 2689310080 },
|
||||
});
|
||||
mappings.insert("RegEx", {
|
||||
{ "search", 4087180739, 3365977994 },
|
||||
{ "search_all", 3354100289, 849021363 },
|
||||
|
@ -1199,15 +1199,6 @@ static GDExtensionVariantPtr gdextension_dictionary_operator_index_const(GDExten
|
||||
return (GDExtensionVariantPtr)&self->operator[](*(const Variant *)p_key);
|
||||
}
|
||||
|
||||
void gdextension_dictionary_set_typed(GDExtensionTypePtr p_self, GDExtensionVariantType p_key_type, GDExtensionConstStringNamePtr p_key_class_name, GDExtensionConstVariantPtr p_key_script, GDExtensionVariantType p_value_type, GDExtensionConstStringNamePtr p_value_class_name, GDExtensionConstVariantPtr p_value_script) {
|
||||
Dictionary *self = reinterpret_cast<Dictionary *>(p_self);
|
||||
const StringName *key_class_name = reinterpret_cast<const StringName *>(p_key_class_name);
|
||||
const Variant *key_script = reinterpret_cast<const Variant *>(p_key_script);
|
||||
const StringName *value_class_name = reinterpret_cast<const StringName *>(p_value_class_name);
|
||||
const Variant *value_script = reinterpret_cast<const Variant *>(p_value_script);
|
||||
self->set_typed((uint32_t)p_key_type, *key_class_name, *key_script, (uint32_t)p_value_type, *value_class_name, *value_script);
|
||||
}
|
||||
|
||||
/* OBJECT API */
|
||||
|
||||
static void gdextension_object_method_bind_call(GDExtensionMethodBindPtr p_method_bind, GDExtensionObjectPtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_arg_count, GDExtensionUninitializedVariantPtr r_return, GDExtensionCallError *r_error) {
|
||||
@ -1308,7 +1299,7 @@ static void gdextension_object_call_script_method(GDExtensionObjectPtr p_object,
|
||||
const StringName method = *reinterpret_cast<const StringName *>(p_method);
|
||||
const Variant **args = (const Variant **)p_args;
|
||||
|
||||
Callable::CallError error; // TODO: Check `error`?
|
||||
Callable::CallError error;
|
||||
memnew_placement(r_return, Variant);
|
||||
*(Variant *)r_return = o->callp(method, args, p_argument_count, error);
|
||||
|
||||
@ -1524,17 +1515,10 @@ static GDExtensionMethodBindPtr gdextension_classdb_get_method_bind(GDExtensionC
|
||||
return (GDExtensionMethodBindPtr)mb;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
static GDExtensionObjectPtr gdextension_classdb_construct_object(GDExtensionConstStringNamePtr p_classname) {
|
||||
const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
|
||||
return (GDExtensionObjectPtr)ClassDB::instantiate_no_placeholders(classname);
|
||||
}
|
||||
#endif
|
||||
|
||||
static GDExtensionObjectPtr gdextension_classdb_construct_object2(GDExtensionConstStringNamePtr p_classname) {
|
||||
const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
|
||||
return (GDExtensionObjectPtr)ClassDB::instantiate_without_postinitialization(classname);
|
||||
}
|
||||
|
||||
static void *gdextension_classdb_get_class_tag(GDExtensionConstStringNamePtr p_classname) {
|
||||
const StringName classname = *reinterpret_cast<const StringName *>(p_classname);
|
||||
@ -1688,7 +1672,6 @@ void gdextension_setup_interface() {
|
||||
REGISTER_INTERFACE_FUNC(array_set_typed);
|
||||
REGISTER_INTERFACE_FUNC(dictionary_operator_index);
|
||||
REGISTER_INTERFACE_FUNC(dictionary_operator_index_const);
|
||||
REGISTER_INTERFACE_FUNC(dictionary_set_typed);
|
||||
REGISTER_INTERFACE_FUNC(object_method_bind_call);
|
||||
REGISTER_INTERFACE_FUNC(object_method_bind_ptrcall);
|
||||
REGISTER_INTERFACE_FUNC(object_destroy);
|
||||
@ -1718,10 +1701,7 @@ void gdextension_setup_interface() {
|
||||
#endif // DISABLE_DEPRECATED
|
||||
REGISTER_INTERFACE_FUNC(callable_custom_create2);
|
||||
REGISTER_INTERFACE_FUNC(callable_custom_get_userdata);
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
REGISTER_INTERFACE_FUNC(classdb_construct_object);
|
||||
#endif // DISABLE_DEPRECATED
|
||||
REGISTER_INTERFACE_FUNC(classdb_construct_object2);
|
||||
REGISTER_INTERFACE_FUNC(classdb_get_method_bind);
|
||||
REGISTER_INTERFACE_FUNC(classdb_get_class_tag);
|
||||
REGISTER_INTERFACE_FUNC(editor_add_plugin);
|
||||
|
@ -268,7 +268,6 @@ typedef void (*GDExtensionClassReference)(GDExtensionClassInstancePtr p_instance
|
||||
typedef void (*GDExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance);
|
||||
typedef void (*GDExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret);
|
||||
typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance)(void *p_class_userdata);
|
||||
typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance2)(void *p_class_userdata, GDExtensionBool p_notify_postinitialize);
|
||||
typedef void (*GDExtensionClassFreeInstance)(void *p_class_userdata, GDExtensionClassInstancePtr p_instance);
|
||||
typedef GDExtensionClassInstancePtr (*GDExtensionClassRecreateInstance)(void *p_class_userdata, GDExtensionObjectPtr p_object);
|
||||
typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual)(void *p_class_userdata, GDExtensionConstStringNamePtr p_name);
|
||||
@ -293,7 +292,7 @@ typedef struct {
|
||||
GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function.
|
||||
GDExtensionClassGetRID get_rid_func;
|
||||
void *class_userdata; // Per-class user data, later accessible in instance bindings.
|
||||
} GDExtensionClassCreationInfo; // Deprecated. Use GDExtensionClassCreationInfo4 instead.
|
||||
} GDExtensionClassCreationInfo; // Deprecated. Use GDExtensionClassCreationInfo3 instead.
|
||||
|
||||
typedef struct {
|
||||
GDExtensionBool is_virtual;
|
||||
@ -326,7 +325,7 @@ typedef struct {
|
||||
GDExtensionClassCallVirtualWithData call_virtual_with_data_func;
|
||||
GDExtensionClassGetRID get_rid_func;
|
||||
void *class_userdata; // Per-class user data, later accessible in instance bindings.
|
||||
} GDExtensionClassCreationInfo2; // Deprecated. Use GDExtensionClassCreationInfo4 instead.
|
||||
} GDExtensionClassCreationInfo2; // Deprecated. Use GDExtensionClassCreationInfo3 instead.
|
||||
|
||||
typedef struct {
|
||||
GDExtensionBool is_virtual;
|
||||
@ -360,40 +359,7 @@ typedef struct {
|
||||
GDExtensionClassCallVirtualWithData call_virtual_with_data_func;
|
||||
GDExtensionClassGetRID get_rid_func;
|
||||
void *class_userdata; // Per-class user data, later accessible in instance bindings.
|
||||
} GDExtensionClassCreationInfo3; // Deprecated. Use GDExtensionClassCreationInfo4 instead.
|
||||
|
||||
typedef struct {
|
||||
GDExtensionBool is_virtual;
|
||||
GDExtensionBool is_abstract;
|
||||
GDExtensionBool is_exposed;
|
||||
GDExtensionBool is_runtime;
|
||||
GDExtensionClassSet set_func;
|
||||
GDExtensionClassGet get_func;
|
||||
GDExtensionClassGetPropertyList get_property_list_func;
|
||||
GDExtensionClassFreePropertyList2 free_property_list_func;
|
||||
GDExtensionClassPropertyCanRevert property_can_revert_func;
|
||||
GDExtensionClassPropertyGetRevert property_get_revert_func;
|
||||
GDExtensionClassValidateProperty validate_property_func;
|
||||
GDExtensionClassNotification2 notification_func;
|
||||
GDExtensionClassToString to_string_func;
|
||||
GDExtensionClassReference reference_func;
|
||||
GDExtensionClassUnreference unreference_func;
|
||||
GDExtensionClassCreateInstance2 create_instance_func; // (Default) constructor; mandatory. If the class is not instantiable, consider making it virtual or abstract.
|
||||
GDExtensionClassFreeInstance free_instance_func; // Destructor; mandatory.
|
||||
GDExtensionClassRecreateInstance recreate_instance_func;
|
||||
// Queries a virtual function by name and returns a callback to invoke the requested virtual function.
|
||||
GDExtensionClassGetVirtual get_virtual_func;
|
||||
// Paired with `call_virtual_with_data_func`, this is an alternative to `get_virtual_func` for extensions that
|
||||
// need or benefit from extra data when calling virtual functions.
|
||||
// Returns user data that will be passed to `call_virtual_with_data_func`.
|
||||
// Returning `NULL` from this function signals to Godot that the virtual function is not overridden.
|
||||
// Data returned from this function should be managed by the extension and must be valid until the extension is deinitialized.
|
||||
// You should supply either `get_virtual_func`, or `get_virtual_call_data_func` with `call_virtual_with_data_func`.
|
||||
GDExtensionClassGetVirtualCallData get_virtual_call_data_func;
|
||||
// Used to call virtual functions when `get_virtual_call_data_func` is not null.
|
||||
GDExtensionClassCallVirtualWithData call_virtual_with_data_func;
|
||||
void *class_userdata; // Per-class user data, later accessible in instance bindings.
|
||||
} GDExtensionClassCreationInfo4;
|
||||
} GDExtensionClassCreationInfo3;
|
||||
|
||||
typedef void *GDExtensionClassLibraryPtr;
|
||||
|
||||
@ -420,9 +386,7 @@ typedef enum {
|
||||
GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT32,
|
||||
GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_UINT64,
|
||||
GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_FLOAT,
|
||||
GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE,
|
||||
GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_CHAR16,
|
||||
GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_CHAR32,
|
||||
GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE
|
||||
} GDExtensionClassMethodArgumentMetadata;
|
||||
|
||||
typedef void (*GDExtensionClassMethodCall)(void *method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
|
||||
@ -2373,22 +2337,6 @@ typedef GDExtensionVariantPtr (*GDExtensionInterfaceDictionaryOperatorIndex)(GDE
|
||||
*/
|
||||
typedef GDExtensionVariantPtr (*GDExtensionInterfaceDictionaryOperatorIndexConst)(GDExtensionConstTypePtr p_self, GDExtensionConstVariantPtr p_key);
|
||||
|
||||
/**
|
||||
* @name dictionary_set_typed
|
||||
* @since 4.4
|
||||
*
|
||||
* Makes a Dictionary into a typed Dictionary.
|
||||
*
|
||||
* @param p_self A pointer to the Dictionary.
|
||||
* @param p_key_type The type of Variant the Dictionary key will store.
|
||||
* @param p_key_class_name A pointer to a StringName with the name of the object (if p_key_type is GDEXTENSION_VARIANT_TYPE_OBJECT).
|
||||
* @param p_key_script A pointer to a Script object (if p_key_type is GDEXTENSION_VARIANT_TYPE_OBJECT and the base class is extended by a script).
|
||||
* @param p_value_type The type of Variant the Dictionary value will store.
|
||||
* @param p_value_class_name A pointer to a StringName with the name of the object (if p_value_type is GDEXTENSION_VARIANT_TYPE_OBJECT).
|
||||
* @param p_value_script A pointer to a Script object (if p_value_type is GDEXTENSION_VARIANT_TYPE_OBJECT and the base class is extended by a script).
|
||||
*/
|
||||
typedef void (*GDExtensionInterfaceDictionarySetTyped)(GDExtensionTypePtr p_self, GDExtensionVariantType p_key_type, GDExtensionConstStringNamePtr p_key_class_name, GDExtensionConstVariantPtr p_key_script, GDExtensionVariantType p_value_type, GDExtensionConstStringNamePtr p_value_class_name, GDExtensionConstVariantPtr p_value_script);
|
||||
|
||||
/* INTERFACE: Object */
|
||||
|
||||
/**
|
||||
@ -2732,7 +2680,6 @@ typedef void *(*GDExtensionInterfaceCallableCustomGetUserData)(GDExtensionConstT
|
||||
/**
|
||||
* @name classdb_construct_object
|
||||
* @since 4.1
|
||||
* @deprecated in Godot 4.4. Use `classdb_construct_object2` instead.
|
||||
*
|
||||
* Constructs an Object of the requested class.
|
||||
*
|
||||
@ -2744,22 +2691,6 @@ typedef void *(*GDExtensionInterfaceCallableCustomGetUserData)(GDExtensionConstT
|
||||
*/
|
||||
typedef GDExtensionObjectPtr (*GDExtensionInterfaceClassdbConstructObject)(GDExtensionConstStringNamePtr p_classname);
|
||||
|
||||
/**
|
||||
* @name classdb_construct_object2
|
||||
* @since 4.4
|
||||
*
|
||||
* Constructs an Object of the requested class.
|
||||
*
|
||||
* The passed class must be a built-in godot class, or an already-registered extension class. In both cases, object_set_instance() should be called to fully initialize the object.
|
||||
*
|
||||
* "NOTIFICATION_POSTINITIALIZE" must be sent after construction.
|
||||
*
|
||||
* @param p_classname A pointer to a StringName with the class name.
|
||||
*
|
||||
* @return A pointer to the newly created Object.
|
||||
*/
|
||||
typedef GDExtensionObjectPtr (*GDExtensionInterfaceClassdbConstructObject2)(GDExtensionConstStringNamePtr p_classname);
|
||||
|
||||
/**
|
||||
* @name classdb_get_method_bind
|
||||
* @since 4.1
|
||||
@ -2791,7 +2722,7 @@ typedef void *(*GDExtensionInterfaceClassdbGetClassTag)(GDExtensionConstStringNa
|
||||
/**
|
||||
* @name classdb_register_extension_class
|
||||
* @since 4.1
|
||||
* @deprecated in Godot 4.2. Use `classdb_register_extension_class4` instead.
|
||||
* @deprecated in Godot 4.2. Use `classdb_register_extension_class3` instead.
|
||||
*
|
||||
* Registers an extension class in the ClassDB.
|
||||
*
|
||||
@ -2807,7 +2738,7 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass)(GDExtensionCla
|
||||
/**
|
||||
* @name classdb_register_extension_class2
|
||||
* @since 4.2
|
||||
* @deprecated in Godot 4.3. Use `classdb_register_extension_class4` instead.
|
||||
* @deprecated in Godot 4.3. Use `classdb_register_extension_class3` instead.
|
||||
*
|
||||
* Registers an extension class in the ClassDB.
|
||||
*
|
||||
@ -2823,7 +2754,6 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass2)(GDExtensionCl
|
||||
/**
|
||||
* @name classdb_register_extension_class3
|
||||
* @since 4.3
|
||||
* @deprecated in Godot 4.4. Use `classdb_register_extension_class4` instead.
|
||||
*
|
||||
* Registers an extension class in the ClassDB.
|
||||
*
|
||||
@ -2836,21 +2766,6 @@ typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass2)(GDExtensionCl
|
||||
*/
|
||||
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass3)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs);
|
||||
|
||||
/**
|
||||
* @name classdb_register_extension_class4
|
||||
* @since 4.4
|
||||
*
|
||||
* Registers an extension class in the ClassDB.
|
||||
*
|
||||
* Provided struct can be safely freed once the function returns.
|
||||
*
|
||||
* @param p_library A pointer the library received by the GDExtension's entry point function.
|
||||
* @param p_class_name A pointer to a StringName with the class name.
|
||||
* @param p_parent_class_name A pointer to a StringName with the parent class name.
|
||||
* @param p_extension_funcs A pointer to a GDExtensionClassCreationInfo2 struct.
|
||||
*/
|
||||
typedef void (*GDExtensionInterfaceClassdbRegisterExtensionClass4)(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs);
|
||||
|
||||
/**
|
||||
* @name classdb_register_extension_class_method
|
||||
* @since 4.1
|
||||
|
@ -1,390 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* gdextension_library_loader.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 "gdextension_library_loader.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/io/dir_access.h"
|
||||
#include "core/version.h"
|
||||
#include "gdextension.h"
|
||||
|
||||
Vector<SharedObject> GDExtensionLibraryLoader::find_extension_dependencies(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature) {
|
||||
Vector<SharedObject> dependencies_shared_objects;
|
||||
if (p_config->has_section("dependencies")) {
|
||||
List<String> config_dependencies;
|
||||
p_config->get_section_keys("dependencies", &config_dependencies);
|
||||
|
||||
for (const String &dependency : config_dependencies) {
|
||||
Vector<String> dependency_tags = dependency.split(".");
|
||||
bool all_tags_met = true;
|
||||
for (int i = 0; i < dependency_tags.size(); i++) {
|
||||
String tag = dependency_tags[i].strip_edges();
|
||||
if (!p_has_feature(tag)) {
|
||||
all_tags_met = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_tags_met) {
|
||||
Dictionary dependency_value = p_config->get_value("dependencies", dependency);
|
||||
for (const Variant *key = dependency_value.next(nullptr); key; key = dependency_value.next(key)) {
|
||||
String dependency_path = *key;
|
||||
String target_path = dependency_value[*key];
|
||||
if (dependency_path.is_relative_path()) {
|
||||
dependency_path = p_path.get_base_dir().path_join(dependency_path);
|
||||
}
|
||||
dependencies_shared_objects.push_back(SharedObject(dependency_path, dependency_tags, target_path));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dependencies_shared_objects;
|
||||
}
|
||||
|
||||
String GDExtensionLibraryLoader::find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags) {
|
||||
// First, check the explicit libraries.
|
||||
if (p_config->has_section("libraries")) {
|
||||
List<String> libraries;
|
||||
p_config->get_section_keys("libraries", &libraries);
|
||||
|
||||
// Iterate the libraries, finding the best matching tags.
|
||||
String best_library_path;
|
||||
Vector<String> best_library_tags;
|
||||
for (const String &E : libraries) {
|
||||
Vector<String> tags = E.split(".");
|
||||
bool all_tags_met = true;
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
String tag = tags[i].strip_edges();
|
||||
if (!p_has_feature(tag)) {
|
||||
all_tags_met = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_tags_met && tags.size() > best_library_tags.size()) {
|
||||
best_library_path = p_config->get_value("libraries", E);
|
||||
best_library_tags = tags;
|
||||
}
|
||||
}
|
||||
|
||||
if (!best_library_path.is_empty()) {
|
||||
if (best_library_path.is_relative_path()) {
|
||||
best_library_path = p_path.get_base_dir().path_join(best_library_path);
|
||||
}
|
||||
if (r_tags != nullptr) {
|
||||
r_tags->append_array(best_library_tags);
|
||||
}
|
||||
return best_library_path;
|
||||
}
|
||||
}
|
||||
|
||||
// Second, try to autodetect.
|
||||
String autodetect_library_prefix;
|
||||
if (p_config->has_section_key("configuration", "autodetect_library_prefix")) {
|
||||
autodetect_library_prefix = p_config->get_value("configuration", "autodetect_library_prefix");
|
||||
}
|
||||
if (!autodetect_library_prefix.is_empty()) {
|
||||
String autodetect_path = autodetect_library_prefix;
|
||||
if (autodetect_path.is_relative_path()) {
|
||||
autodetect_path = p_path.get_base_dir().path_join(autodetect_path);
|
||||
}
|
||||
|
||||
// Find the folder and file parts of the prefix.
|
||||
String folder;
|
||||
String file_prefix;
|
||||
if (DirAccess::dir_exists_absolute(autodetect_path)) {
|
||||
folder = autodetect_path;
|
||||
} else if (DirAccess::dir_exists_absolute(autodetect_path.get_base_dir())) {
|
||||
folder = autodetect_path.get_base_dir();
|
||||
file_prefix = autodetect_path.get_file();
|
||||
} else {
|
||||
ERR_FAIL_V_MSG(String(), vformat("Error in extension: %s. Could not find folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix));
|
||||
}
|
||||
|
||||
// Open the folder.
|
||||
Ref<DirAccess> dir = DirAccess::open(folder);
|
||||
ERR_FAIL_COND_V_MSG(dir.is_null(), String(), vformat("Error in extension: %s. Could not open folder for automatic detection of libraries files. autodetect_library_prefix=\"%s\"", p_path, autodetect_library_prefix));
|
||||
|
||||
// Iterate the files and check the prefixes, finding the best matching file.
|
||||
String best_file;
|
||||
Vector<String> best_file_tags;
|
||||
dir->list_dir_begin();
|
||||
String file_name = dir->_get_next();
|
||||
while (file_name != "") {
|
||||
if (!dir->current_is_dir() && file_name.begins_with(file_prefix)) {
|
||||
// Check if the files matches all requested feature tags.
|
||||
String tags_str = file_name.trim_prefix(file_prefix);
|
||||
tags_str = tags_str.trim_suffix(tags_str.get_extension());
|
||||
|
||||
Vector<String> tags = tags_str.split(".", false);
|
||||
bool all_tags_met = true;
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
String tag = tags[i].strip_edges();
|
||||
if (!p_has_feature(tag)) {
|
||||
all_tags_met = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If all tags are found in the feature list, and we found more tags than before, use this file.
|
||||
if (all_tags_met && tags.size() > best_file_tags.size()) {
|
||||
best_file_tags = tags;
|
||||
best_file = file_name;
|
||||
}
|
||||
}
|
||||
file_name = dir->_get_next();
|
||||
}
|
||||
|
||||
if (!best_file.is_empty()) {
|
||||
String library_path = folder.path_join(best_file);
|
||||
if (r_tags != nullptr) {
|
||||
r_tags->append_array(best_file_tags);
|
||||
}
|
||||
return library_path;
|
||||
}
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
Error GDExtensionLibraryLoader::open_library(const String &p_path) {
|
||||
Error err = parse_gdextension_file(p_path);
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
String abs_path = ProjectSettings::get_singleton()->globalize_path(library_path);
|
||||
|
||||
Vector<String> abs_dependencies_paths;
|
||||
if (!library_dependencies.is_empty()) {
|
||||
for (const SharedObject &dependency : library_dependencies) {
|
||||
abs_dependencies_paths.push_back(ProjectSettings::get_singleton()->globalize_path(dependency.path));
|
||||
}
|
||||
}
|
||||
|
||||
OS::GDExtensionData data = {
|
||||
true, // also_set_library_path
|
||||
&library_path, // r_resolved_path
|
||||
Engine::get_singleton()->is_editor_hint(), // generate_temp_files
|
||||
&abs_dependencies_paths, // library_dependencies
|
||||
};
|
||||
|
||||
err = OS::get_singleton()->open_dynamic_library(is_static_library ? String() : abs_path, library, &data);
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error GDExtensionLibraryLoader::initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
p_extension->set_reloadable(is_reloadable && Engine::get_singleton()->is_extension_reloading_enabled());
|
||||
#endif
|
||||
|
||||
for (const KeyValue<String, String> &icon : class_icon_paths) {
|
||||
p_extension->class_icon_paths[icon.key] = icon.value;
|
||||
}
|
||||
|
||||
void *entry_funcptr = nullptr;
|
||||
|
||||
Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(library, entry_symbol, entry_funcptr, false);
|
||||
|
||||
if (err != OK) {
|
||||
ERR_PRINT("GDExtension entry point '" + entry_symbol + "' not found in library " + library_path);
|
||||
return err;
|
||||
}
|
||||
|
||||
GDExtensionInitializationFunction initialization_function = (GDExtensionInitializationFunction)entry_funcptr;
|
||||
|
||||
GDExtensionBool ret = initialization_function(p_get_proc_address, p_extension.ptr(), r_initialization);
|
||||
|
||||
if (ret) {
|
||||
return OK;
|
||||
} else {
|
||||
ERR_PRINT("GDExtension initialization function '" + entry_symbol + "' returned an error.");
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
void GDExtensionLibraryLoader::close_library() {
|
||||
OS::get_singleton()->close_dynamic_library(library);
|
||||
library = nullptr;
|
||||
}
|
||||
|
||||
bool GDExtensionLibraryLoader::is_library_open() const {
|
||||
return library != nullptr;
|
||||
}
|
||||
|
||||
bool GDExtensionLibraryLoader::has_library_changed() const {
|
||||
#ifdef TOOLS_ENABLED
|
||||
// Check only that the last modified time is different (rather than checking
|
||||
// that it's newer) since some OS's (namely Windows) will preserve the modified
|
||||
// time by default when copying files.
|
||||
if (FileAccess::get_modified_time(resource_path) != resource_last_modified_time) {
|
||||
return true;
|
||||
}
|
||||
if (FileAccess::get_modified_time(library_path) != library_last_modified_time) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) {
|
||||
resource_path = p_path;
|
||||
|
||||
Ref<ConfigFile> config;
|
||||
config.instantiate();
|
||||
|
||||
Error err = config->load(p_path);
|
||||
|
||||
if (err != OK) {
|
||||
ERR_PRINT("Error loading GDExtension configuration file: " + p_path);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!config->has_section_key("configuration", "entry_symbol")) {
|
||||
ERR_PRINT("GDExtension configuration file must contain a \"configuration/entry_symbol\" key: " + p_path);
|
||||
return ERR_INVALID_DATA;
|
||||
}
|
||||
|
||||
entry_symbol = config->get_value("configuration", "entry_symbol");
|
||||
|
||||
uint32_t compatibility_minimum[3] = { 0, 0, 0 };
|
||||
if (config->has_section_key("configuration", "compatibility_minimum")) {
|
||||
String compat_string = config->get_value("configuration", "compatibility_minimum");
|
||||
Vector<int> parts = compat_string.split_ints(".");
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
if (i >= 3) {
|
||||
break;
|
||||
}
|
||||
if (parts[i] >= 0) {
|
||||
compatibility_minimum[i] = parts[i];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ERR_PRINT("GDExtension configuration file must contain a \"configuration/compatibility_minimum\" key: " + p_path);
|
||||
return ERR_INVALID_DATA;
|
||||
}
|
||||
|
||||
if (compatibility_minimum[0] < 4 || (compatibility_minimum[0] == 4 && compatibility_minimum[1] == 0)) {
|
||||
ERR_PRINT(vformat("GDExtension's compatibility_minimum (%d.%d.%d) must be at least 4.1.0: %s", compatibility_minimum[0], compatibility_minimum[1], compatibility_minimum[2], p_path));
|
||||
return ERR_INVALID_DATA;
|
||||
}
|
||||
|
||||
bool compatible = true;
|
||||
// Check version lexicographically.
|
||||
if (VERSION_MAJOR != compatibility_minimum[0]) {
|
||||
compatible = VERSION_MAJOR > compatibility_minimum[0];
|
||||
} else if (VERSION_MINOR != compatibility_minimum[1]) {
|
||||
compatible = VERSION_MINOR > compatibility_minimum[1];
|
||||
} else {
|
||||
compatible = VERSION_PATCH >= compatibility_minimum[2];
|
||||
}
|
||||
if (!compatible) {
|
||||
ERR_PRINT(vformat("GDExtension only compatible with Godot version %d.%d.%d or later: %s", compatibility_minimum[0], compatibility_minimum[1], compatibility_minimum[2], p_path));
|
||||
return ERR_INVALID_DATA;
|
||||
}
|
||||
|
||||
// Optionally check maximum compatibility.
|
||||
if (config->has_section_key("configuration", "compatibility_maximum")) {
|
||||
uint32_t compatibility_maximum[3] = { 0, 0, 0 };
|
||||
String compat_string = config->get_value("configuration", "compatibility_maximum");
|
||||
Vector<int> parts = compat_string.split_ints(".");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (i < parts.size() && parts[i] >= 0) {
|
||||
compatibility_maximum[i] = parts[i];
|
||||
} else {
|
||||
// If a version part is missing, set the maximum to an arbitrary high value.
|
||||
compatibility_maximum[i] = 9999;
|
||||
}
|
||||
}
|
||||
|
||||
compatible = true;
|
||||
if (VERSION_MAJOR != compatibility_maximum[0]) {
|
||||
compatible = VERSION_MAJOR < compatibility_maximum[0];
|
||||
} else if (VERSION_MINOR != compatibility_maximum[1]) {
|
||||
compatible = VERSION_MINOR < compatibility_maximum[1];
|
||||
}
|
||||
#if VERSION_PATCH
|
||||
// #if check to avoid -Wtype-limits warning when 0.
|
||||
else {
|
||||
compatible = VERSION_PATCH <= compatibility_maximum[2];
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!compatible) {
|
||||
ERR_PRINT(vformat("GDExtension only compatible with Godot version %s or earlier: %s", compat_string, p_path));
|
||||
return ERR_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
library_path = find_extension_library(p_path, config, [](const String &p_feature) { return OS::get_singleton()->has_feature(p_feature); });
|
||||
|
||||
if (library_path.is_empty()) {
|
||||
const String os_arch = OS::get_singleton()->get_name().to_lower() + "." + Engine::get_singleton()->get_architecture_name();
|
||||
ERR_PRINT(vformat("No GDExtension library found for current OS and architecture (%s) in configuration file: %s", os_arch, p_path));
|
||||
return ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
is_static_library = library_path.ends_with(".a") || library_path.ends_with(".xcframework");
|
||||
|
||||
if (!library_path.is_resource_file() && !library_path.is_absolute_path()) {
|
||||
library_path = p_path.get_base_dir().path_join(library_path);
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
is_reloadable = config->get_value("configuration", "reloadable", false);
|
||||
|
||||
update_last_modified_time(
|
||||
FileAccess::get_modified_time(resource_path),
|
||||
FileAccess::get_modified_time(library_path));
|
||||
#endif
|
||||
|
||||
library_dependencies = find_extension_dependencies(p_path, config, [](const String &p_feature) { return OS::get_singleton()->has_feature(p_feature); });
|
||||
|
||||
// Handle icons if any are specified.
|
||||
if (config->has_section("icons")) {
|
||||
List<String> keys;
|
||||
config->get_section_keys("icons", &keys);
|
||||
for (const String &key : keys) {
|
||||
String icon_path = config->get_value("icons", key);
|
||||
if (icon_path.is_relative_path()) {
|
||||
icon_path = p_path.get_base_dir().path_join(icon_path);
|
||||
}
|
||||
|
||||
class_icon_paths[key] = icon_path;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* gdextension_library_loader.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 GDEXTENSION_LIBRARY_LOADER_H
|
||||
#define GDEXTENSION_LIBRARY_LOADER_H
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "core/extension/gdextension_loader.h"
|
||||
#include "core/io/config_file.h"
|
||||
#include "core/os/shared_object.h"
|
||||
|
||||
class GDExtensionLibraryLoader : public GDExtensionLoader {
|
||||
friend class GDExtensionManager;
|
||||
friend class GDExtension;
|
||||
|
||||
private:
|
||||
String resource_path;
|
||||
|
||||
void *library = nullptr; // pointer if valid.
|
||||
String library_path;
|
||||
String entry_symbol;
|
||||
|
||||
bool is_static_library = false;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
bool is_reloadable = false;
|
||||
#endif
|
||||
|
||||
Vector<SharedObject> library_dependencies;
|
||||
|
||||
HashMap<String, String> class_icon_paths;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
uint64_t resource_last_modified_time = 0;
|
||||
uint64_t library_last_modified_time = 0;
|
||||
|
||||
void update_last_modified_time(uint64_t p_resource_last_modified_time, uint64_t p_library_last_modified_time) {
|
||||
resource_last_modified_time = p_resource_last_modified_time;
|
||||
library_last_modified_time = p_library_last_modified_time;
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
static String find_extension_library(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature, PackedStringArray *r_tags = nullptr);
|
||||
static Vector<SharedObject> find_extension_dependencies(const String &p_path, Ref<ConfigFile> p_config, std::function<bool(String)> p_has_feature);
|
||||
|
||||
virtual Error open_library(const String &p_path) override;
|
||||
virtual Error initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) override;
|
||||
virtual void close_library() override;
|
||||
virtual bool is_library_open() const override;
|
||||
virtual bool has_library_changed() const override;
|
||||
|
||||
Error parse_gdextension_file(const String &p_path);
|
||||
};
|
||||
|
||||
#endif // GDEXTENSION_LIBRARY_LOADER_H
|
@ -1,47 +0,0 @@
|
||||
/**************************************************************************/
|
||||
/* gdextension_loader.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 GDEXTENSION_LOADER_H
|
||||
#define GDEXTENSION_LOADER_H
|
||||
|
||||
#include "core/object/ref_counted.h"
|
||||
|
||||
class GDExtension;
|
||||
|
||||
class GDExtensionLoader : public RefCounted {
|
||||
public:
|
||||
virtual Error open_library(const String &p_path) = 0;
|
||||
virtual Error initialize(GDExtensionInterfaceGetProcAddress p_get_proc_address, const Ref<GDExtension> &p_extension, GDExtensionInitialization *r_initialization) = 0;
|
||||
virtual void close_library() = 0;
|
||||
virtual bool is_library_open() const = 0;
|
||||
virtual bool has_library_changed() const = 0;
|
||||
};
|
||||
|
||||
#endif // GDEXTENSION_LOADER_H
|
@ -31,19 +31,14 @@
|
||||
#include "gdextension_manager.h"
|
||||
|
||||
#include "core/extension/gdextension_compat_hashes.h"
|
||||
#include "core/extension/gdextension_library_loader.h"
|
||||
#include "core/io/dir_access.h"
|
||||
#include "core/io/file_access.h"
|
||||
#include "core/object/script_language.h"
|
||||
|
||||
GDExtensionManager::LoadStatus GDExtensionManager::_load_extension_internal(const Ref<GDExtension> &p_extension, bool p_first_load) {
|
||||
GDExtensionManager::LoadStatus GDExtensionManager::_load_extension_internal(const Ref<GDExtension> &p_extension) {
|
||||
if (level >= 0) { // Already initialized up to some level.
|
||||
int32_t minimum_level = 0;
|
||||
if (!p_first_load) {
|
||||
minimum_level = p_extension->get_minimum_library_initialization_level();
|
||||
if (minimum_level < MIN(level, GDExtension::INITIALIZATION_LEVEL_SCENE)) {
|
||||
return LOAD_STATUS_NEEDS_RESTART;
|
||||
}
|
||||
int32_t minimum_level = p_extension->get_minimum_library_initialization_level();
|
||||
if (minimum_level < MIN(level, GDExtension::INITIALIZATION_LEVEL_SCENE)) {
|
||||
return LOAD_STATUS_NEEDS_RESTART;
|
||||
}
|
||||
// Initialize up to current level.
|
||||
for (int32_t i = minimum_level; i <= level; i++) {
|
||||
@ -55,20 +50,10 @@ GDExtensionManager::LoadStatus GDExtensionManager::_load_extension_internal(cons
|
||||
gdextension_class_icon_paths[kv.key] = kv.value;
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
// Signals that a new extension is loaded so GDScript can register new class names.
|
||||
emit_signal("extension_loaded", p_extension);
|
||||
#endif
|
||||
|
||||
return LOAD_STATUS_OK;
|
||||
}
|
||||
|
||||
GDExtensionManager::LoadStatus GDExtensionManager::_unload_extension_internal(const Ref<GDExtension> &p_extension) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
// Signals that a new extension is unloading so GDScript can unregister class names.
|
||||
emit_signal("extension_unloading", p_extension);
|
||||
#endif
|
||||
|
||||
if (level >= 0) { // Already initialized up to some level.
|
||||
// Deinitialize down from current level.
|
||||
for (int32_t i = level; i >= GDExtension::INITIALIZATION_LEVEL_CORE; i--) {
|
||||
@ -84,31 +69,19 @@ GDExtensionManager::LoadStatus GDExtensionManager::_unload_extension_internal(co
|
||||
}
|
||||
|
||||
GDExtensionManager::LoadStatus GDExtensionManager::load_extension(const String &p_path) {
|
||||
Ref<GDExtensionLibraryLoader> loader;
|
||||
loader.instantiate();
|
||||
return GDExtensionManager::get_singleton()->load_extension_with_loader(p_path, loader);
|
||||
}
|
||||
|
||||
GDExtensionManager::LoadStatus GDExtensionManager::load_extension_with_loader(const String &p_path, const Ref<GDExtensionLoader> &p_loader) {
|
||||
DEV_ASSERT(p_loader.is_valid());
|
||||
|
||||
if (gdextension_map.has(p_path)) {
|
||||
return LOAD_STATUS_ALREADY_LOADED;
|
||||
}
|
||||
|
||||
Ref<GDExtension> extension;
|
||||
extension.instantiate();
|
||||
Error err = extension->open_library(p_path, p_loader);
|
||||
if (err != OK) {
|
||||
Ref<GDExtension> extension = ResourceLoader::load(p_path);
|
||||
if (extension.is_null()) {
|
||||
return LOAD_STATUS_FAILED;
|
||||
}
|
||||
|
||||
LoadStatus status = _load_extension_internal(extension, true);
|
||||
LoadStatus status = _load_extension_internal(extension);
|
||||
if (status != LOAD_STATUS_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
extension->set_path(p_path);
|
||||
gdextension_map[p_path] = extension;
|
||||
return LOAD_STATUS_OK;
|
||||
}
|
||||
@ -144,12 +117,12 @@ GDExtensionManager::LoadStatus GDExtensionManager::reload_extension(const String
|
||||
extension->close_library();
|
||||
}
|
||||
|
||||
Error err = extension->open_library(p_path, extension->loader);
|
||||
Error err = GDExtensionResourceLoader::load_gdextension_resource(p_path, extension);
|
||||
if (err != OK) {
|
||||
return LOAD_STATUS_FAILED;
|
||||
}
|
||||
|
||||
status = _load_extension_internal(extension, false);
|
||||
status = _load_extension_internal(extension);
|
||||
if (status != LOAD_STATUS_OK) {
|
||||
return status;
|
||||
}
|
||||
@ -288,71 +261,6 @@ void GDExtensionManager::reload_extensions() {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GDExtensionManager::ensure_extensions_loaded(const HashSet<String> &p_extensions) {
|
||||
Vector<String> extensions_added;
|
||||
Vector<String> extensions_removed;
|
||||
|
||||
for (const String &E : p_extensions) {
|
||||
if (!is_extension_loaded(E)) {
|
||||
extensions_added.push_back(E);
|
||||
}
|
||||
}
|
||||
|
||||
Vector<String> loaded_extensions = get_loaded_extensions();
|
||||
for (const String &loaded_extension : loaded_extensions) {
|
||||
if (!p_extensions.has(loaded_extension)) {
|
||||
// The extension may not have a .gdextension file.
|
||||
if (!FileAccess::exists(loaded_extension)) {
|
||||
extensions_removed.push_back(loaded_extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String extension_list_config_file = GDExtension::get_extension_list_config_file();
|
||||
if (p_extensions.size()) {
|
||||
if (extensions_added.size() || extensions_removed.size()) {
|
||||
// Extensions were added or removed.
|
||||
Ref<FileAccess> f = FileAccess::open(extension_list_config_file, FileAccess::WRITE);
|
||||
for (const String &E : p_extensions) {
|
||||
f->store_line(E);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (loaded_extensions.size() || FileAccess::exists(extension_list_config_file)) {
|
||||
// Extensions were removed.
|
||||
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
|
||||
da->remove(extension_list_config_file);
|
||||
}
|
||||
}
|
||||
|
||||
bool needs_restart = false;
|
||||
for (const String &extension : extensions_added) {
|
||||
GDExtensionManager::LoadStatus st = GDExtensionManager::get_singleton()->load_extension(extension);
|
||||
if (st == GDExtensionManager::LOAD_STATUS_NEEDS_RESTART) {
|
||||
needs_restart = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (const String &extension : extensions_removed) {
|
||||
GDExtensionManager::LoadStatus st = GDExtensionManager::get_singleton()->unload_extension(extension);
|
||||
if (st == GDExtensionManager::LOAD_STATUS_NEEDS_RESTART) {
|
||||
needs_restart = true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (extensions_added.size() || extensions_removed.size()) {
|
||||
// Emitting extensions_reloaded so EditorNode can reload Inspector and regenerate documentation.
|
||||
emit_signal("extensions_reloaded");
|
||||
|
||||
// Reload all scripts to clear out old references.
|
||||
callable_mp_static(&GDExtensionManager::_reload_all_scripts).call_deferred();
|
||||
}
|
||||
#endif
|
||||
|
||||
return needs_restart;
|
||||
}
|
||||
|
||||
GDExtensionManager *GDExtensionManager::get_singleton() {
|
||||
return singleton;
|
||||
}
|
||||
@ -373,8 +281,6 @@ void GDExtensionManager::_bind_methods() {
|
||||
BIND_ENUM_CONSTANT(LOAD_STATUS_NEEDS_RESTART);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("extensions_reloaded"));
|
||||
ADD_SIGNAL(MethodInfo("extension_loaded", PropertyInfo(Variant::OBJECT, "extension", PROPERTY_HINT_RESOURCE_TYPE, "GDExtension")));
|
||||
ADD_SIGNAL(MethodInfo("extension_unloading", PropertyInfo(Variant::OBJECT, "extension", PROPERTY_HINT_RESOURCE_TYPE, "GDExtension")));
|
||||
}
|
||||
|
||||
GDExtensionManager *GDExtensionManager::singleton = nullptr;
|
||||
|
@ -54,7 +54,7 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
LoadStatus _load_extension_internal(const Ref<GDExtension> &p_extension, bool p_first_load);
|
||||
LoadStatus _load_extension_internal(const Ref<GDExtension> &p_extension);
|
||||
LoadStatus _unload_extension_internal(const Ref<GDExtension> &p_extension);
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
@ -63,7 +63,6 @@ private:
|
||||
|
||||
public:
|
||||
LoadStatus load_extension(const String &p_path);
|
||||
LoadStatus load_extension_with_loader(const String &p_path, const Ref<GDExtensionLoader> &p_loader);
|
||||
LoadStatus reload_extension(const String &p_path);
|
||||
LoadStatus unload_extension(const String &p_path);
|
||||
bool is_extension_loaded(const String &p_path) const;
|
||||
@ -85,7 +84,6 @@ public:
|
||||
|
||||
void load_extensions();
|
||||
void reload_extensions();
|
||||
bool ensure_extensions_loaded(const HashSet<String> &p_extensions);
|
||||
|
||||
GDExtensionManager();
|
||||
~GDExtensionManager();
|
||||
|
@ -55,10 +55,10 @@ def generate_mod_version(argcount, const=False, returns=False):
|
||||
|
||||
proto_ex = """
|
||||
#define EXBIND$VER($RETTYPE m_name$ARG) \\
|
||||
GDVIRTUAL$VER_REQUIRED($RETTYPE_##m_name$ARG)\\
|
||||
GDVIRTUAL$VER($RETTYPE_##m_name$ARG)\\
|
||||
virtual $RETVAL m_name($FUNCARGS) $CONST override { \\
|
||||
$RETPRE\\
|
||||
GDVIRTUAL_CALL(_##m_name$CALLARGS$RETREF);\\
|
||||
GDVIRTUAL_REQUIRED_CALL(_##m_name$CALLARGS$RETREF);\\
|
||||
$RETPOST\\
|
||||
}
|
||||
"""
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
@ -513,49 +513,21 @@ void Input::joy_connection_changed(int p_idx, bool p_connected, const String &p_
|
||||
|
||||
Vector3 Input::get_gravity() const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (!gravity_enabled) {
|
||||
WARN_PRINT_ONCE("`input_devices/sensors/enable_gravity` is not enabled in project settings.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return gravity;
|
||||
}
|
||||
|
||||
Vector3 Input::get_accelerometer() const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (!accelerometer_enabled) {
|
||||
WARN_PRINT_ONCE("`input_devices/sensors/enable_accelerometer` is not enabled in project settings.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return accelerometer;
|
||||
}
|
||||
|
||||
Vector3 Input::get_magnetometer() const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (!magnetometer_enabled) {
|
||||
WARN_PRINT_ONCE("`input_devices/sensors/enable_magnetometer` is not enabled in project settings.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return magnetometer;
|
||||
}
|
||||
|
||||
Vector3 Input::get_gyroscope() const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (!gyroscope_enabled) {
|
||||
WARN_PRINT_ONCE("`input_devices/sensors/enable_gyroscope` is not enabled in project settings.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return gyroscope;
|
||||
}
|
||||
|
||||
@ -1711,11 +1683,6 @@ Input::Input() {
|
||||
// Always use standard behavior in the editor.
|
||||
legacy_just_pressed_behavior = false;
|
||||
}
|
||||
|
||||
accelerometer_enabled = GLOBAL_DEF_RST_BASIC("input_devices/sensors/enable_accelerometer", false);
|
||||
gravity_enabled = GLOBAL_DEF_RST_BASIC("input_devices/sensors/enable_gravity", false);
|
||||
gyroscope_enabled = GLOBAL_DEF_RST_BASIC("input_devices/sensors/enable_gyroscope", false);
|
||||
magnetometer_enabled = GLOBAL_DEF_RST_BASIC("input_devices/sensors/enable_magnetometer", false);
|
||||
}
|
||||
|
||||
Input::~Input() {
|
||||
|
@ -92,13 +92,9 @@ private:
|
||||
RBSet<JoyButton> joy_buttons_pressed;
|
||||
RBMap<JoyAxis, float> _joy_axis;
|
||||
//RBMap<StringName,int> custom_action_press;
|
||||
bool gravity_enabled = false;
|
||||
Vector3 gravity;
|
||||
bool accelerometer_enabled = false;
|
||||
Vector3 accelerometer;
|
||||
bool magnetometer_enabled = false;
|
||||
Vector3 magnetometer;
|
||||
bool gyroscope_enabled = false;
|
||||
Vector3 gyroscope;
|
||||
Vector2 mouse_pos;
|
||||
int64_t mouse_window = 0;
|
||||
|
@ -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::INVALID || p_axis > JoyAxis::MAX);
|
||||
ERR_FAIL_COND(p_axis < JoyAxis::LEFT_X || p_axis > JoyAxis::MAX);
|
||||
|
||||
axis = p_axis;
|
||||
emit_changed();
|
||||
|
@ -400,7 +400,6 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
|
||||
{ "ui_filedialog_refresh", TTRC("Refresh") },
|
||||
{ "ui_filedialog_show_hidden", TTRC("Show Hidden") },
|
||||
{ "ui_swap_input_direction ", TTRC("Swap Input Direction") },
|
||||
{ "ui_unicode_start", TTRC("Start Unicode Character Input") },
|
||||
{ "", ""}
|
||||
/* clang-format on */
|
||||
};
|
||||
@ -755,10 +754,6 @@ const HashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
|
||||
inputs.push_back(InputEventKey::create_reference(Key::KP_ENTER));
|
||||
default_builtin_cache.insert("ui_text_submit", inputs);
|
||||
|
||||
inputs = List<Ref<InputEvent>>();
|
||||
inputs.push_back(InputEventKey::create_reference(Key::U | KeyModifierMask::CTRL | KeyModifierMask::SHIFT));
|
||||
default_builtin_cache.insert("ui_unicode_start", inputs);
|
||||
|
||||
// ///// UI Graph Shortcuts /////
|
||||
|
||||
inputs = List<Ref<InputEvent>>();
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
|
@ -33,12 +33,12 @@
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/io/file_access.h"
|
||||
|
||||
DTLSServer *(*DTLSServer::_create)(bool p_notify_postinitialize) = nullptr;
|
||||
DTLSServer *(*DTLSServer::_create)() = nullptr;
|
||||
bool DTLSServer::available = false;
|
||||
|
||||
DTLSServer *DTLSServer::create(bool p_notify_postinitialize) {
|
||||
DTLSServer *DTLSServer::create() {
|
||||
if (_create) {
|
||||
return _create(p_notify_postinitialize);
|
||||
return _create();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -38,14 +38,14 @@ class DTLSServer : public RefCounted {
|
||||
GDCLASS(DTLSServer, RefCounted);
|
||||
|
||||
protected:
|
||||
static DTLSServer *(*_create)(bool p_notify_postinitialize);
|
||||
static DTLSServer *(*_create)();
|
||||
static void _bind_methods();
|
||||
|
||||
static bool available;
|
||||
|
||||
public:
|
||||
static bool is_available();
|
||||
static DTLSServer *create(bool p_notify_postinitialize = true);
|
||||
static DTLSServer *create();
|
||||
|
||||
virtual Error setup(Ref<TLSOptions> p_options) = 0;
|
||||
virtual void stop() = 0;
|
||||
|
@ -59,9 +59,11 @@ bool FileAccess::exists(const String &p_name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Using file_exists because it's faster than trying to open the file.
|
||||
Ref<FileAccess> ret = create_for_path(p_name);
|
||||
return ret->file_exists(p_name);
|
||||
Ref<FileAccess> f = open(p_name, READ);
|
||||
if (f.is_null()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileAccess::_set_access_type(AccessType p_access) {
|
||||
@ -223,44 +225,59 @@ String FileAccess::fix_path(const String &p_path) const {
|
||||
}
|
||||
|
||||
/* these are all implemented for ease of porting, then can later be optimized */
|
||||
uint8_t FileAccess::get_8() const {
|
||||
uint8_t data = 0;
|
||||
get_buffer(&data, sizeof(uint8_t));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
uint16_t FileAccess::get_16() const {
|
||||
uint16_t data = 0;
|
||||
get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint16_t));
|
||||
uint16_t res;
|
||||
uint8_t a, b;
|
||||
|
||||
a = get_8();
|
||||
b = get_8();
|
||||
|
||||
if (big_endian) {
|
||||
data = BSWAP16(data);
|
||||
SWAP(a, b);
|
||||
}
|
||||
|
||||
return data;
|
||||
res = b;
|
||||
res <<= 8;
|
||||
res |= a;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t FileAccess::get_32() const {
|
||||
uint32_t data = 0;
|
||||
get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint32_t));
|
||||
uint32_t res;
|
||||
uint16_t a, b;
|
||||
|
||||
a = get_16();
|
||||
b = get_16();
|
||||
|
||||
if (big_endian) {
|
||||
data = BSWAP32(data);
|
||||
SWAP(a, b);
|
||||
}
|
||||
|
||||
return data;
|
||||
res = b;
|
||||
res <<= 16;
|
||||
res |= a;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint64_t FileAccess::get_64() const {
|
||||
uint64_t data = 0;
|
||||
get_buffer(reinterpret_cast<uint8_t *>(&data), sizeof(uint64_t));
|
||||
uint64_t res;
|
||||
uint32_t a, b;
|
||||
|
||||
a = get_32();
|
||||
b = get_32();
|
||||
|
||||
if (big_endian) {
|
||||
data = BSWAP64(data);
|
||||
SWAP(a, b);
|
||||
}
|
||||
|
||||
return data;
|
||||
res = b;
|
||||
res <<= 32;
|
||||
res |= a;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
float FileAccess::get_float() const {
|
||||
@ -450,6 +467,17 @@ String FileAccess::get_as_text(bool p_skip_cr) const {
|
||||
return text;
|
||||
}
|
||||
|
||||
uint64_t FileAccess::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
|
||||
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
|
||||
|
||||
uint64_t i = 0;
|
||||
for (i = 0; i < p_length && !eof_reached(); i++) {
|
||||
p_dst[i] = get_8();
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
|
||||
Vector<uint8_t> data;
|
||||
|
||||
@ -462,7 +490,7 @@ Vector<uint8_t> FileAccess::get_buffer(int64_t p_length) const {
|
||||
ERR_FAIL_COND_V_MSG(err != OK, data, "Can't resize data to " + itos(p_length) + " elements.");
|
||||
|
||||
uint8_t *w = data.ptrw();
|
||||
int64_t len = get_buffer(w, p_length);
|
||||
int64_t len = get_buffer(&w[0], p_length);
|
||||
|
||||
if (len < p_length) {
|
||||
data.resize(len);
|
||||
@ -486,32 +514,46 @@ String FileAccess::get_as_utf8_string(bool p_skip_cr) const {
|
||||
return s;
|
||||
}
|
||||
|
||||
void FileAccess::store_8(uint8_t p_dest) {
|
||||
store_buffer(&p_dest, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
void FileAccess::store_16(uint16_t p_dest) {
|
||||
uint8_t a, b;
|
||||
|
||||
a = p_dest & 0xFF;
|
||||
b = p_dest >> 8;
|
||||
|
||||
if (big_endian) {
|
||||
p_dest = BSWAP16(p_dest);
|
||||
SWAP(a, b);
|
||||
}
|
||||
|
||||
store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint16_t));
|
||||
store_8(a);
|
||||
store_8(b);
|
||||
}
|
||||
|
||||
void FileAccess::store_32(uint32_t p_dest) {
|
||||
uint16_t a, b;
|
||||
|
||||
a = p_dest & 0xFFFF;
|
||||
b = p_dest >> 16;
|
||||
|
||||
if (big_endian) {
|
||||
p_dest = BSWAP32(p_dest);
|
||||
SWAP(a, b);
|
||||
}
|
||||
|
||||
store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint32_t));
|
||||
store_16(a);
|
||||
store_16(b);
|
||||
}
|
||||
|
||||
void FileAccess::store_64(uint64_t p_dest) {
|
||||
uint32_t a, b;
|
||||
|
||||
a = p_dest & 0xFFFFFFFF;
|
||||
b = p_dest >> 32;
|
||||
|
||||
if (big_endian) {
|
||||
p_dest = BSWAP64(p_dest);
|
||||
SWAP(a, b);
|
||||
}
|
||||
|
||||
store_buffer(reinterpret_cast<uint8_t *>(&p_dest), sizeof(uint64_t));
|
||||
store_32(a);
|
||||
store_32(b);
|
||||
}
|
||||
|
||||
void FileAccess::store_real(real_t p_real) {
|
||||
@ -668,11 +710,22 @@ void FileAccess::store_csv_line(const Vector<String> &p_values, const String &p_
|
||||
store_line(line);
|
||||
}
|
||||
|
||||
void FileAccess::store_buffer(const uint8_t *p_src, uint64_t p_length) {
|
||||
ERR_FAIL_COND(!p_src && p_length > 0);
|
||||
for (uint64_t i = 0; i < p_length; i++) {
|
||||
store_8(p_src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void FileAccess::store_buffer(const Vector<uint8_t> &p_buffer) {
|
||||
uint64_t len = p_buffer.size();
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t *r = p_buffer.ptr();
|
||||
|
||||
store_buffer(r, len);
|
||||
store_buffer(&r[0], len);
|
||||
}
|
||||
|
||||
void FileAccess::store_var(const Variant &p_var, bool p_full_objects) {
|
||||
|
@ -137,7 +137,7 @@ public:
|
||||
|
||||
virtual bool eof_reached() const = 0; ///< reading passed EOF
|
||||
|
||||
virtual uint8_t get_8() const; ///< get a byte
|
||||
virtual uint8_t get_8() const = 0; ///< get a byte
|
||||
virtual uint16_t get_16() const; ///< get 16 bits uint
|
||||
virtual uint32_t get_32() const; ///< get 32 bits uint
|
||||
virtual uint64_t get_64() const; ///< get 64 bits uint
|
||||
@ -148,7 +148,7 @@ public:
|
||||
|
||||
Variant get_var(bool p_allow_objects = false) const;
|
||||
|
||||
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const = 0; ///< get an array of bytes, needs to be overwritten by children.
|
||||
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const; ///< get an array of bytes
|
||||
Vector<uint8_t> get_buffer(int64_t p_length) const;
|
||||
virtual String get_line() const;
|
||||
virtual String get_token() const;
|
||||
@ -168,7 +168,7 @@ public:
|
||||
|
||||
virtual Error resize(int64_t p_length) = 0;
|
||||
virtual void flush() = 0;
|
||||
virtual void store_8(uint8_t p_dest); ///< store a byte
|
||||
virtual void store_8(uint8_t p_dest) = 0; ///< store a byte
|
||||
virtual void store_16(uint16_t p_dest); ///< store 16 bits uint
|
||||
virtual void store_32(uint32_t p_dest); ///< store 32 bits uint
|
||||
virtual void store_64(uint64_t p_dest); ///< store 64 bits uint
|
||||
@ -184,7 +184,7 @@ public:
|
||||
virtual void store_pascal_string(const String &p_string);
|
||||
virtual String get_pascal_string();
|
||||
|
||||
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) = 0; ///< store an array of bytes, needs to be overwritten by children.
|
||||
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length); ///< store an array of bytes
|
||||
void store_buffer(const Vector<uint8_t> &p_buffer);
|
||||
|
||||
void store_var(const Variant &p_var, bool p_full_objects = false);
|
||||
|
@ -260,6 +260,38 @@ bool FileAccessCompressed::eof_reached() const {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t FileAccessCompressed::get_8() const {
|
||||
ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
|
||||
ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
|
||||
|
||||
if (at_end) {
|
||||
read_eof = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t ret = read_ptr[read_pos];
|
||||
|
||||
read_pos++;
|
||||
if (read_pos >= read_block_size) {
|
||||
read_block++;
|
||||
|
||||
if (read_block < read_block_count) {
|
||||
//read another block of compressed data
|
||||
f->get_buffer(comp_buffer.ptrw(), read_blocks[read_block].csize);
|
||||
int total = Compression::decompress(buffer.ptrw(), read_blocks.size() == 1 ? read_total : block_size, comp_buffer.ptr(), read_blocks[read_block].csize, cmode);
|
||||
ERR_FAIL_COND_V_MSG(total == -1, 0, "Compressed file is corrupt.");
|
||||
read_block_size = read_block == read_block_count - 1 ? read_total % block_size : block_size;
|
||||
read_pos = 0;
|
||||
|
||||
} else {
|
||||
read_block--;
|
||||
at_end = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t FileAccessCompressed::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
|
||||
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
|
||||
ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
|
||||
@ -309,13 +341,12 @@ void FileAccessCompressed::flush() {
|
||||
// compressed files keep data in memory till close()
|
||||
}
|
||||
|
||||
void FileAccessCompressed::store_buffer(const uint8_t *p_src, uint64_t p_length) {
|
||||
void FileAccessCompressed::store_8(uint8_t p_dest) {
|
||||
ERR_FAIL_COND_MSG(f.is_null(), "File must be opened before use.");
|
||||
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
|
||||
|
||||
WRITE_FIT(p_length);
|
||||
memcpy(write_ptr + write_pos, p_src, p_length);
|
||||
write_pos += p_length;
|
||||
WRITE_FIT(1);
|
||||
write_ptr[write_pos++] = p_dest;
|
||||
}
|
||||
|
||||
bool FileAccessCompressed::file_exists(const String &p_name) {
|
||||
|
@ -83,13 +83,14 @@ public:
|
||||
|
||||
virtual bool eof_reached() const override; ///< reading passed EOF
|
||||
|
||||
virtual uint8_t get_8() const override; ///< get a byte
|
||||
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
|
||||
|
||||
virtual Error get_error() const override; ///< get last error
|
||||
|
||||
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
|
||||
virtual void flush() override;
|
||||
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
|
||||
virtual void store_8(uint8_t p_dest) override; ///< store a byte
|
||||
|
||||
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic) {
|
||||
ERR_FAIL_COND_V_MSG(file.is_valid(), ERR_ALREADY_IN_USE, "Can't open file while another file from path '" + file->get_path_absolute() + "' is open.");
|
||||
ERR_FAIL_COND_V_MSG(file != nullptr, ERR_ALREADY_IN_USE, "Can't open file while another file from path '" + file->get_path_absolute() + "' is open.");
|
||||
ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER);
|
||||
|
||||
pos = 0;
|
||||
@ -162,7 +162,7 @@ void FileAccessEncrypted::_close() {
|
||||
}
|
||||
|
||||
bool FileAccessEncrypted::is_open() const {
|
||||
return file.is_valid();
|
||||
return file != nullptr;
|
||||
}
|
||||
|
||||
String FileAccessEncrypted::get_path() const {
|
||||
@ -206,13 +206,26 @@ bool FileAccessEncrypted::eof_reached() const {
|
||||
return eofed;
|
||||
}
|
||||
|
||||
uint8_t FileAccessEncrypted::get_8() const {
|
||||
ERR_FAIL_COND_V_MSG(writing, 0, "File has not been opened in read mode.");
|
||||
if (pos >= get_length()) {
|
||||
eofed = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t b = data[pos];
|
||||
pos++;
|
||||
return b;
|
||||
}
|
||||
|
||||
uint64_t FileAccessEncrypted::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
|
||||
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
|
||||
ERR_FAIL_COND_V_MSG(writing, -1, "File has not been opened in read mode.");
|
||||
|
||||
uint64_t to_copy = MIN(p_length, get_length() - pos);
|
||||
memcpy(p_dst, data.ptr() + pos, to_copy);
|
||||
pos += to_copy;
|
||||
for (uint64_t i = 0; i < to_copy; i++) {
|
||||
p_dst[i] = data[pos++];
|
||||
}
|
||||
|
||||
if (to_copy < p_length) {
|
||||
eofed = true;
|
||||
@ -229,12 +242,17 @@ void FileAccessEncrypted::store_buffer(const uint8_t *p_src, uint64_t p_length)
|
||||
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
|
||||
ERR_FAIL_COND(!p_src && p_length > 0);
|
||||
|
||||
if (pos + p_length >= get_length()) {
|
||||
if (pos < get_length()) {
|
||||
for (uint64_t i = 0; i < p_length; i++) {
|
||||
store_8(p_src[i]);
|
||||
}
|
||||
} else if (pos == get_length()) {
|
||||
data.resize(pos + p_length);
|
||||
for (uint64_t i = 0; i < p_length; i++) {
|
||||
data.write[pos + i] = p_src[i];
|
||||
}
|
||||
pos += p_length;
|
||||
}
|
||||
|
||||
memcpy(data.ptrw() + pos, p_src, p_length);
|
||||
pos += p_length;
|
||||
}
|
||||
|
||||
void FileAccessEncrypted::flush() {
|
||||
@ -243,6 +261,18 @@ void FileAccessEncrypted::flush() {
|
||||
// encrypted files keep data in memory till close()
|
||||
}
|
||||
|
||||
void FileAccessEncrypted::store_8(uint8_t p_dest) {
|
||||
ERR_FAIL_COND_MSG(!writing, "File has not been opened in write mode.");
|
||||
|
||||
if (pos < get_length()) {
|
||||
data.write[pos] = p_dest;
|
||||
pos++;
|
||||
} else if (pos == get_length()) {
|
||||
data.push_back(p_dest);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
bool FileAccessEncrypted::file_exists(const String &p_name) {
|
||||
Ref<FileAccess> fa = FileAccess::open(p_name, FileAccess::READ);
|
||||
if (fa.is_null()) {
|
||||
|
@ -73,12 +73,14 @@ public:
|
||||
|
||||
virtual bool eof_reached() const override; ///< reading passed EOF
|
||||
|
||||
virtual uint8_t get_8() const override; ///< get a byte
|
||||
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
|
||||
|
||||
virtual Error get_error() const override; ///< get last error
|
||||
|
||||
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
|
||||
virtual void flush() override;
|
||||
virtual void store_8(uint8_t p_dest) override; ///< store a byte
|
||||
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
|
||||
|
||||
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
|
||||
|
@ -122,6 +122,16 @@ bool FileAccessMemory::eof_reached() const {
|
||||
return pos >= length;
|
||||
}
|
||||
|
||||
uint8_t FileAccessMemory::get_8() const {
|
||||
uint8_t ret = 0;
|
||||
if (pos < length) {
|
||||
ret = data[pos];
|
||||
}
|
||||
++pos;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t FileAccessMemory::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
|
||||
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
|
||||
ERR_FAIL_NULL_V(data, -1);
|
||||
@ -147,12 +157,16 @@ void FileAccessMemory::flush() {
|
||||
ERR_FAIL_NULL(data);
|
||||
}
|
||||
|
||||
void FileAccessMemory::store_8(uint8_t p_byte) {
|
||||
ERR_FAIL_NULL(data);
|
||||
ERR_FAIL_COND(pos >= length);
|
||||
data[pos++] = p_byte;
|
||||
}
|
||||
|
||||
void FileAccessMemory::store_buffer(const uint8_t *p_src, uint64_t p_length) {
|
||||
ERR_FAIL_COND(!p_src && p_length > 0);
|
||||
|
||||
uint64_t left = length - pos;
|
||||
uint64_t write = MIN(p_length, left);
|
||||
|
||||
if (write < p_length) {
|
||||
WARN_PRINT("Writing less data than requested");
|
||||
}
|
||||
|
@ -55,12 +55,15 @@ public:
|
||||
|
||||
virtual bool eof_reached() const override; ///< reading passed EOF
|
||||
|
||||
virtual uint8_t get_8() const override; ///< get a byte
|
||||
|
||||
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override; ///< get an array of bytes
|
||||
|
||||
virtual Error get_error() const override; ///< get last error
|
||||
|
||||
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
|
||||
virtual void flush() override;
|
||||
virtual void store_8(uint8_t p_byte) override; ///< store a byte
|
||||
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
|
||||
|
||||
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
|
||||
|
@ -102,22 +102,6 @@ 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() {
|
||||
@ -329,6 +313,17 @@ bool FileAccessPack::eof_reached() const {
|
||||
return eof;
|
||||
}
|
||||
|
||||
uint8_t FileAccessPack::get_8() const {
|
||||
ERR_FAIL_COND_V_MSG(f.is_null(), 0, "File must be opened before use.");
|
||||
if (pos >= pf.size) {
|
||||
eof = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pos++;
|
||||
return f->get_8();
|
||||
}
|
||||
|
||||
uint64_t FileAccessPack::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
|
||||
ERR_FAIL_COND_V_MSG(f.is_null(), -1, "File must be opened before use.");
|
||||
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
|
||||
@ -371,6 +366,10 @@ void FileAccessPack::flush() {
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
void FileAccessPack::store_8(uint8_t p_dest) {
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
void FileAccessPack::store_buffer(const uint8_t *p_src, uint64_t p_length) {
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
@ -111,7 +111,6 @@ 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; }
|
||||
@ -119,8 +118,6 @@ 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);
|
||||
|
||||
@ -172,6 +169,8 @@ public:
|
||||
|
||||
virtual bool eof_reached() const override;
|
||||
|
||||
virtual uint8_t get_8() const override;
|
||||
|
||||
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
|
||||
|
||||
virtual void set_big_endian(bool p_big_endian) override;
|
||||
@ -180,6 +179,8 @@ public:
|
||||
|
||||
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
|
||||
virtual void flush() override;
|
||||
virtual void store_8(uint8_t p_dest) override;
|
||||
|
||||
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
|
||||
|
||||
virtual bool file_exists(const String &p_name) override;
|
||||
|
@ -291,6 +291,12 @@ bool FileAccessZip::eof_reached() const {
|
||||
return at_eof;
|
||||
}
|
||||
|
||||
uint8_t FileAccessZip::get_8() const {
|
||||
uint8_t ret = 0;
|
||||
get_buffer(&ret, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t FileAccessZip::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
|
||||
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
|
||||
ERR_FAIL_NULL_V(zfile, -1);
|
||||
@ -322,7 +328,7 @@ void FileAccessZip::flush() {
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
void FileAccessZip::store_buffer(const uint8_t *p_src, uint64_t p_length) {
|
||||
void FileAccessZip::store_8(uint8_t p_dest) {
|
||||
ERR_FAIL();
|
||||
}
|
||||
|
||||
|
@ -95,13 +95,14 @@ public:
|
||||
|
||||
virtual bool eof_reached() const override; ///< reading passed EOF
|
||||
|
||||
virtual uint8_t get_8() const override; ///< get a byte
|
||||
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
|
||||
|
||||
virtual Error get_error() const override; ///< get last error
|
||||
|
||||
virtual Error resize(int64_t p_length) override { return ERR_UNAVAILABLE; }
|
||||
virtual void flush() override;
|
||||
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
|
||||
virtual void store_8(uint8_t p_dest) override; ///< store a byte
|
||||
|
||||
virtual bool file_exists(const String &p_name) override; ///< return true if a file exists
|
||||
|
||||
|
@ -42,9 +42,9 @@ const char *HTTPClient::_methods[METHOD_MAX] = {
|
||||
"PATCH"
|
||||
};
|
||||
|
||||
HTTPClient *HTTPClient::create(bool p_notify_postinitialize) {
|
||||
HTTPClient *HTTPClient::create() {
|
||||
if (_create) {
|
||||
return _create(p_notify_postinitialize);
|
||||
return _create();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -158,12 +158,12 @@ protected:
|
||||
Error _request_raw(Method p_method, const String &p_url, const Vector<String> &p_headers, const Vector<uint8_t> &p_body);
|
||||
Error _request(Method p_method, const String &p_url, const Vector<String> &p_headers, const String &p_body = String());
|
||||
|
||||
static HTTPClient *(*_create)(bool p_notify_postinitialize);
|
||||
static HTTPClient *(*_create)();
|
||||
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
static HTTPClient *create(bool p_notify_postinitialize = true);
|
||||
static HTTPClient *create();
|
||||
|
||||
String query_string_from_dict(const Dictionary &p_dict);
|
||||
Error verify_headers(const Vector<String> &p_headers);
|
||||
|
@ -35,8 +35,8 @@
|
||||
#include "core/io/stream_peer_tls.h"
|
||||
#include "core/version.h"
|
||||
|
||||
HTTPClient *HTTPClientTCP::_create_func(bool p_notify_postinitialize) {
|
||||
return static_cast<HTTPClient *>(ClassDB::creator<HTTPClientTCP>(p_notify_postinitialize));
|
||||
HTTPClient *HTTPClientTCP::_create_func() {
|
||||
return memnew(HTTPClientTCP);
|
||||
}
|
||||
|
||||
Error HTTPClientTCP::connect_to_host(const String &p_host, int p_port, Ref<TLSOptions> p_options) {
|
||||
@ -792,6 +792,6 @@ HTTPClientTCP::HTTPClientTCP() {
|
||||
request_buffer.instantiate();
|
||||
}
|
||||
|
||||
HTTPClient *(*HTTPClient::_create)(bool p_notify_postinitialize) = HTTPClientTCP::_create_func;
|
||||
HTTPClient *(*HTTPClient::_create)() = HTTPClientTCP::_create_func;
|
||||
|
||||
#endif // WEB_ENABLED
|
||||
|
@ -76,7 +76,7 @@ private:
|
||||
Error _get_http_data(uint8_t *p_buffer, int p_bytes, int &r_received);
|
||||
|
||||
public:
|
||||
static HTTPClient *_create_func(bool p_notify_postinitialize);
|
||||
static HTTPClient *_create_func();
|
||||
|
||||
Error request(Method p_method, const String &p_url, const Vector<String> &p_headers, const uint8_t *p_body, int p_body_size) override;
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
|
||||
#include "image.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/error/error_list.h"
|
||||
#include "core/error/error_macros.h"
|
||||
#include "core/io/image_loader.h"
|
||||
@ -502,38 +501,6 @@ static void _convert(int p_width, int p_height, const uint8_t *p_src, uint8_t *p
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, uint32_t read_channels, uint32_t write_channels, T def_zero, T def_one>
|
||||
static void _convert_fast(int p_width, int p_height, const T *p_src, T *p_dst) {
|
||||
uint32_t dst_count = 0;
|
||||
uint32_t src_count = 0;
|
||||
|
||||
const int resolution = p_width * p_height;
|
||||
|
||||
for (int i = 0; i < resolution; i++) {
|
||||
memcpy(p_dst + dst_count, p_src + src_count, MIN(read_channels, write_channels) * sizeof(T));
|
||||
|
||||
if constexpr (write_channels > read_channels) {
|
||||
const T def_value[4] = { def_zero, def_zero, def_zero, def_one };
|
||||
memcpy(p_dst + dst_count + read_channels, &def_value[read_channels], (write_channels - read_channels) * sizeof(T));
|
||||
}
|
||||
|
||||
dst_count += write_channels;
|
||||
src_count += read_channels;
|
||||
}
|
||||
}
|
||||
|
||||
static bool _are_formats_compatible(Image::Format p_format0, Image::Format p_format1) {
|
||||
if (p_format0 <= Image::FORMAT_RGBA8 && p_format1 <= Image::FORMAT_RGBA8) {
|
||||
return true;
|
||||
} else if (p_format0 <= Image::FORMAT_RGBAH && p_format0 >= Image::FORMAT_RH && p_format1 <= Image::FORMAT_RGBAH && p_format1 >= Image::FORMAT_RH) {
|
||||
return true;
|
||||
} else if (p_format0 <= Image::FORMAT_RGBAF && p_format0 >= Image::FORMAT_RF && p_format1 <= Image::FORMAT_RGBAF && p_format1 >= Image::FORMAT_RF) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Image::convert(Format p_new_format) {
|
||||
ERR_FAIL_INDEX_MSG(p_new_format, FORMAT_MAX, "The Image format specified (" + itos(p_new_format) + ") is out of range. See Image's Format enum.");
|
||||
if (data.size() == 0) {
|
||||
@ -550,7 +517,7 @@ void Image::convert(Format p_new_format) {
|
||||
if (Image::is_format_compressed(format) || Image::is_format_compressed(p_new_format)) {
|
||||
ERR_FAIL_MSG("Cannot convert to <-> from compressed formats. Use compress() and decompress() instead.");
|
||||
|
||||
} else if (!_are_formats_compatible(format, p_new_format)) {
|
||||
} else if (format > FORMAT_RGBA8 || p_new_format > FORMAT_RGBA8) {
|
||||
//use put/set pixel which is slower but works with non byte formats
|
||||
Image new_img(width, height, mipmaps, p_new_format);
|
||||
|
||||
@ -681,78 +648,6 @@ void Image::convert(Format p_new_format) {
|
||||
case FORMAT_RGBA8 | (FORMAT_RGB8 << 8):
|
||||
_convert<3, true, 3, false, false, false>(mip_width, mip_height, rptr, wptr);
|
||||
break;
|
||||
case FORMAT_RH | (FORMAT_RGH << 8):
|
||||
_convert_fast<uint16_t, 1, 2, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RH | (FORMAT_RGBH << 8):
|
||||
_convert_fast<uint16_t, 1, 3, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RH | (FORMAT_RGBAH << 8):
|
||||
_convert_fast<uint16_t, 1, 4, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGH | (FORMAT_RH << 8):
|
||||
_convert_fast<uint16_t, 2, 1, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGH | (FORMAT_RGBH << 8):
|
||||
_convert_fast<uint16_t, 2, 3, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGH | (FORMAT_RGBAH << 8):
|
||||
_convert_fast<uint16_t, 2, 4, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBH | (FORMAT_RH << 8):
|
||||
_convert_fast<uint16_t, 3, 1, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBH | (FORMAT_RGH << 8):
|
||||
_convert_fast<uint16_t, 3, 2, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBH | (FORMAT_RGBAH << 8):
|
||||
_convert_fast<uint16_t, 3, 4, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBAH | (FORMAT_RH << 8):
|
||||
_convert_fast<uint16_t, 4, 1, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBAH | (FORMAT_RGH << 8):
|
||||
_convert_fast<uint16_t, 4, 2, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBAH | (FORMAT_RGBH << 8):
|
||||
_convert_fast<uint16_t, 4, 3, 0x0000, 0x3C00>(mip_width, mip_height, (const uint16_t *)rptr, (uint16_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RF | (FORMAT_RGF << 8):
|
||||
_convert_fast<uint32_t, 1, 2, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RF | (FORMAT_RGBF << 8):
|
||||
_convert_fast<uint32_t, 1, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RF | (FORMAT_RGBAF << 8):
|
||||
_convert_fast<uint32_t, 1, 4, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGF | (FORMAT_RF << 8):
|
||||
_convert_fast<uint32_t, 2, 1, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGF | (FORMAT_RGBF << 8):
|
||||
_convert_fast<uint32_t, 2, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGF | (FORMAT_RGBAF << 8):
|
||||
_convert_fast<uint32_t, 2, 4, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBF | (FORMAT_RF << 8):
|
||||
_convert_fast<uint32_t, 3, 1, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBF | (FORMAT_RGF << 8):
|
||||
_convert_fast<uint32_t, 3, 2, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBF | (FORMAT_RGBAF << 8):
|
||||
_convert_fast<uint32_t, 3, 4, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBAF | (FORMAT_RF << 8):
|
||||
_convert_fast<uint32_t, 4, 1, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBAF | (FORMAT_RGF << 8):
|
||||
_convert_fast<uint32_t, 4, 2, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||
break;
|
||||
case FORMAT_RGBAF | (FORMAT_RGBF << 8):
|
||||
_convert_fast<uint32_t, 4, 3, 0x00000000, 0x3F800000>(mip_width, mip_height, (const uint32_t *)rptr, (uint32_t *)wptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -866,10 +761,12 @@ 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) {
|
||||
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;
|
||||
enum {
|
||||
FRAC_BITS = 8,
|
||||
FRAC_LEN = (1 << FRAC_BITS),
|
||||
FRAC_HALF = (FRAC_LEN >> 1),
|
||||
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
|
||||
@ -2733,40 +2630,6 @@ Error Image::compress(CompressMode p_mode, CompressSource p_source, ASTCFormat p
|
||||
Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels, ASTCFormat p_astc_format) {
|
||||
ERR_FAIL_COND_V(data.is_empty(), ERR_INVALID_DATA);
|
||||
|
||||
// RenderingDevice only.
|
||||
if (GLOBAL_GET("rendering/textures/vram_compression/compress_with_gpu")) {
|
||||
switch (p_mode) {
|
||||
case COMPRESS_BPTC: {
|
||||
// BC7 is unsupported currently.
|
||||
if ((format >= FORMAT_RF && format <= FORMAT_RGBE9995) && _image_compress_bptc_rd_func) {
|
||||
Error result = _image_compress_bptc_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;
|
||||
|
||||
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: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (p_mode) {
|
||||
case COMPRESS_S3TC: {
|
||||
ERR_FAIL_NULL_V(_image_compress_bc_func, ERR_UNAVAILABLE);
|
||||
@ -3148,8 +3011,6 @@ void (*Image::_image_compress_bptc_func)(Image *, Image::UsedChannels) = nullptr
|
||||
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;
|
||||
@ -3599,7 +3460,6 @@ void Image::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("fix_alpha_edges"), &Image::fix_alpha_edges);
|
||||
ClassDB::bind_method(D_METHOD("premultiply_alpha"), &Image::premultiply_alpha);
|
||||
ClassDB::bind_method(D_METHOD("srgb_to_linear"), &Image::srgb_to_linear);
|
||||
ClassDB::bind_method(D_METHOD("linear_to_srgb"), &Image::linear_to_srgb);
|
||||
ClassDB::bind_method(D_METHOD("normal_map_to_xy"), &Image::normal_map_to_xy);
|
||||
ClassDB::bind_method(D_METHOD("rgbe_to_srgb"), &Image::rgbe_to_srgb);
|
||||
ClassDB::bind_method(D_METHOD("bump_map_to_normal_map", "bump_scale"), &Image::bump_map_to_normal_map, DEFVAL(1.0));
|
||||
@ -3836,33 +3696,6 @@ void Image::bump_map_to_normal_map(float bump_scale) {
|
||||
data = result_image;
|
||||
}
|
||||
|
||||
bool Image::detect_signed(bool p_include_mips) const {
|
||||
ERR_FAIL_COND_V(is_compressed(), false);
|
||||
|
||||
if (format >= Image::FORMAT_RH && format <= Image::FORMAT_RGBAH) {
|
||||
const uint16_t *img_data = reinterpret_cast<const uint16_t *>(data.ptr());
|
||||
const uint64_t img_size = p_include_mips ? (data.size() / 2) : (width * height * get_format_pixel_size(format) / 2);
|
||||
|
||||
for (uint64_t i = 0; i < img_size; i++) {
|
||||
if ((img_data[i] & 0x8000) != 0 && (img_data[i] & 0x7fff) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (format >= Image::FORMAT_RF && format <= Image::FORMAT_RGBAF) {
|
||||
const uint32_t *img_data = reinterpret_cast<const uint32_t *>(data.ptr());
|
||||
const uint64_t img_size = p_include_mips ? (data.size() / 4) : (width * height * get_format_pixel_size(format) / 4);
|
||||
|
||||
for (uint64_t i = 0; i < img_size; i++) {
|
||||
if ((img_data[i] & 0x80000000) != 0 && (img_data[i] & 0x7fffffff) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Image::srgb_to_linear() {
|
||||
if (data.size() == 0) {
|
||||
return;
|
||||
@ -3894,37 +3727,6 @@ void Image::srgb_to_linear() {
|
||||
}
|
||||
}
|
||||
|
||||
void Image::linear_to_srgb() {
|
||||
if (data.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
static const uint8_t lin2srgb[256] = { 0, 12, 21, 28, 33, 38, 42, 46, 49, 52, 55, 58, 61, 63, 66, 68, 70, 73, 75, 77, 79, 81, 82, 84, 86, 88, 89, 91, 93, 94, 96, 97, 99, 100, 102, 103, 104, 106, 107, 109, 110, 111, 112, 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156, 157, 157, 158, 159, 160, 161, 161, 162, 163, 164, 165, 165, 166, 167, 168, 168, 169, 170, 171, 171, 172, 173, 174, 174, 175, 176, 176, 177, 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 237, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255 };
|
||||
|
||||
ERR_FAIL_COND(format != FORMAT_RGB8 && format != FORMAT_RGBA8);
|
||||
|
||||
if (format == FORMAT_RGBA8) {
|
||||
int len = data.size() / 4;
|
||||
uint8_t *data_ptr = data.ptrw();
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
data_ptr[(i << 2) + 0] = lin2srgb[data_ptr[(i << 2) + 0]];
|
||||
data_ptr[(i << 2) + 1] = lin2srgb[data_ptr[(i << 2) + 1]];
|
||||
data_ptr[(i << 2) + 2] = lin2srgb[data_ptr[(i << 2) + 2]];
|
||||
}
|
||||
|
||||
} else if (format == FORMAT_RGB8) {
|
||||
int len = data.size() / 3;
|
||||
uint8_t *data_ptr = data.ptrw();
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
data_ptr[(i * 3) + 0] = lin2srgb[data_ptr[(i * 3) + 0]];
|
||||
data_ptr[(i * 3) + 1] = lin2srgb[data_ptr[(i * 3) + 1]];
|
||||
data_ptr[(i * 3) + 2] = lin2srgb[data_ptr[(i * 3) + 2]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Image::premultiply_alpha() {
|
||||
if (data.size() == 0) {
|
||||
return;
|
||||
@ -4237,7 +4039,7 @@ Dictionary Image::compute_image_metrics(const Ref<Image> p_compared_image, bool
|
||||
result["root_mean_squared"] = INFINITY;
|
||||
result["peak_snr"] = 0.0f;
|
||||
|
||||
ERR_FAIL_COND_V(p_compared_image.is_null(), result);
|
||||
ERR_FAIL_NULL_V(p_compared_image, result);
|
||||
Error err = OK;
|
||||
Ref<Image> compared_image = duplicate(true);
|
||||
if (compared_image->is_compressed()) {
|
||||
|
@ -159,9 +159,6 @@ public:
|
||||
static void (*_image_compress_etc2_func)(Image *, UsedChannels p_channels);
|
||||
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 *);
|
||||
static void (*_image_decompress_etc1)(Image *);
|
||||
@ -386,14 +383,11 @@ public:
|
||||
void fix_alpha_edges();
|
||||
void premultiply_alpha();
|
||||
void srgb_to_linear();
|
||||
void linear_to_srgb();
|
||||
void normal_map_to_xy();
|
||||
Ref<Image> rgbe_to_srgb();
|
||||
Ref<Image> get_image_from_mipmap(int p_mipmap) const;
|
||||
void bump_map_to_normal_map(float bump_scale = 1.0);
|
||||
|
||||
bool detect_signed(bool p_include_mips = true) const;
|
||||
|
||||
void blit_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest);
|
||||
void blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2i &p_src_rect, const Point2i &p_dest);
|
||||
void blend_rect(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest);
|
||||
|
@ -81,17 +81,17 @@ struct _IP_ResolverPrivate {
|
||||
continue;
|
||||
}
|
||||
|
||||
MutexLock lock(mutex);
|
||||
mutex.lock();
|
||||
List<IPAddress> response;
|
||||
String hostname = queue[i].hostname;
|
||||
IP::Type type = queue[i].type;
|
||||
lock.temp_unlock();
|
||||
mutex.unlock();
|
||||
|
||||
// We should not lock while resolving the hostname,
|
||||
// only when modifying the queue.
|
||||
IP::get_singleton()->_resolve_hostname(response, hostname, type);
|
||||
|
||||
lock.temp_relock();
|
||||
MutexLock lock(mutex);
|
||||
// Could have been completed by another function, or deleted.
|
||||
if (queue[i].status.get() != IP::RESOLVER_STATUS_WAITING) {
|
||||
continue;
|
||||
@ -131,22 +131,21 @@ PackedStringArray IP::resolve_hostname_addresses(const String &p_hostname, Type
|
||||
List<IPAddress> res;
|
||||
String key = _IP_ResolverPrivate::get_cache_key(p_hostname, p_type);
|
||||
|
||||
{
|
||||
MutexLock lock(resolver->mutex);
|
||||
if (resolver->cache.has(key)) {
|
||||
res = resolver->cache[key];
|
||||
} else {
|
||||
// This should be run unlocked so the resolver thread can keep resolving
|
||||
// other requests.
|
||||
lock.temp_unlock();
|
||||
_resolve_hostname(res, p_hostname, p_type);
|
||||
lock.temp_relock();
|
||||
// We might be overriding another result, but we don't care as long as the result is valid.
|
||||
if (res.size()) {
|
||||
resolver->cache[key] = res;
|
||||
}
|
||||
resolver->mutex.lock();
|
||||
if (resolver->cache.has(key)) {
|
||||
res = resolver->cache[key];
|
||||
} else {
|
||||
// This should be run unlocked so the resolver thread can keep resolving
|
||||
// other requests.
|
||||
resolver->mutex.unlock();
|
||||
_resolve_hostname(res, p_hostname, p_type);
|
||||
resolver->mutex.lock();
|
||||
// We might be overriding another result, but we don't care as long as the result is valid.
|
||||
if (res.size()) {
|
||||
resolver->cache[key] = res;
|
||||
}
|
||||
}
|
||||
resolver->mutex.unlock();
|
||||
|
||||
PackedStringArray result;
|
||||
for (const IPAddress &E : res) {
|
||||
|
748
core/io/json.cpp
748
core/io/json.cpp
@ -588,756 +588,10 @@ void JSON::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_error_line"), &JSON::get_error_line);
|
||||
ClassDB::bind_method(D_METHOD("get_error_message"), &JSON::get_error_message);
|
||||
|
||||
ClassDB::bind_static_method("JSON", D_METHOD("to_native", "json", "allow_classes", "allow_scripts"), &JSON::to_native, DEFVAL(false), DEFVAL(false));
|
||||
ClassDB::bind_static_method("JSON", D_METHOD("from_native", "variant", "allow_classes", "allow_scripts"), &JSON::from_native, DEFVAL(false), DEFVAL(false));
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::NIL, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT), "set_data", "get_data"); // Ensures that it can be serialized as binary.
|
||||
}
|
||||
|
||||
#define GDTYPE "__gdtype"
|
||||
#define VALUES "values"
|
||||
#define PASS_ARG p_allow_classes, p_allow_scripts
|
||||
|
||||
Variant JSON::from_native(const Variant &p_variant, bool p_allow_classes, bool p_allow_scripts) {
|
||||
switch (p_variant.get_type()) {
|
||||
case Variant::NIL: {
|
||||
Dictionary nil;
|
||||
nil[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return nil;
|
||||
} break;
|
||||
case Variant::BOOL: {
|
||||
return p_variant;
|
||||
} break;
|
||||
case Variant::INT: {
|
||||
return p_variant;
|
||||
} break;
|
||||
case Variant::FLOAT: {
|
||||
return p_variant;
|
||||
} break;
|
||||
case Variant::STRING: {
|
||||
return p_variant;
|
||||
} break;
|
||||
case Variant::VECTOR2: {
|
||||
Dictionary d;
|
||||
Vector2 v = p_variant;
|
||||
Array values;
|
||||
values.push_back(v.x);
|
||||
values.push_back(v.y);
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::VECTOR2I: {
|
||||
Dictionary d;
|
||||
Vector2i v = p_variant;
|
||||
Array values;
|
||||
values.push_back(v.x);
|
||||
values.push_back(v.y);
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::RECT2: {
|
||||
Dictionary d;
|
||||
Rect2 r = p_variant;
|
||||
d["position"] = from_native(r.position);
|
||||
d["size"] = from_native(r.size);
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::RECT2I: {
|
||||
Dictionary d;
|
||||
Rect2i r = p_variant;
|
||||
d["position"] = from_native(r.position);
|
||||
d["size"] = from_native(r.size);
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::VECTOR3: {
|
||||
Dictionary d;
|
||||
Vector3 v = p_variant;
|
||||
Array values;
|
||||
values.push_back(v.x);
|
||||
values.push_back(v.y);
|
||||
values.push_back(v.z);
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::VECTOR3I: {
|
||||
Dictionary d;
|
||||
Vector3i v = p_variant;
|
||||
Array values;
|
||||
values.push_back(v.x);
|
||||
values.push_back(v.y);
|
||||
values.push_back(v.z);
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::TRANSFORM2D: {
|
||||
Dictionary d;
|
||||
Transform2D t = p_variant;
|
||||
d["x"] = from_native(t[0]);
|
||||
d["y"] = from_native(t[1]);
|
||||
d["origin"] = from_native(t[2]);
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::VECTOR4: {
|
||||
Dictionary d;
|
||||
Vector4 v = p_variant;
|
||||
Array values;
|
||||
values.push_back(v.x);
|
||||
values.push_back(v.y);
|
||||
values.push_back(v.z);
|
||||
values.push_back(v.w);
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::VECTOR4I: {
|
||||
Dictionary d;
|
||||
Vector4i v = p_variant;
|
||||
Array values;
|
||||
values.push_back(v.x);
|
||||
values.push_back(v.y);
|
||||
values.push_back(v.z);
|
||||
values.push_back(v.w);
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::PLANE: {
|
||||
Dictionary d;
|
||||
Plane p = p_variant;
|
||||
d["normal"] = from_native(p.normal);
|
||||
d["d"] = p.d;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::QUATERNION: {
|
||||
Dictionary d;
|
||||
Quaternion q = p_variant;
|
||||
Array values;
|
||||
values.push_back(q.x);
|
||||
values.push_back(q.y);
|
||||
values.push_back(q.z);
|
||||
values.push_back(q.w);
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::AABB: {
|
||||
Dictionary d;
|
||||
AABB aabb = p_variant;
|
||||
d["position"] = from_native(aabb.position);
|
||||
d["size"] = from_native(aabb.size);
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::BASIS: {
|
||||
Dictionary d;
|
||||
Basis t = p_variant;
|
||||
d["x"] = from_native(t.get_column(0));
|
||||
d["y"] = from_native(t.get_column(1));
|
||||
d["z"] = from_native(t.get_column(2));
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::TRANSFORM3D: {
|
||||
Dictionary d;
|
||||
Transform3D t = p_variant;
|
||||
d["basis"] = from_native(t.basis);
|
||||
d["origin"] = from_native(t.origin);
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::PROJECTION: {
|
||||
Dictionary d;
|
||||
Projection t = p_variant;
|
||||
d["x"] = from_native(t[0]);
|
||||
d["y"] = from_native(t[1]);
|
||||
d["z"] = from_native(t[2]);
|
||||
d["w"] = from_native(t[3]);
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::COLOR: {
|
||||
Dictionary d;
|
||||
Color c = p_variant;
|
||||
Array values;
|
||||
values.push_back(c.r);
|
||||
values.push_back(c.g);
|
||||
values.push_back(c.b);
|
||||
values.push_back(c.a);
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::STRING_NAME: {
|
||||
Dictionary d;
|
||||
d["name"] = String(p_variant);
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::NODE_PATH: {
|
||||
Dictionary d;
|
||||
d["path"] = String(p_variant);
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::RID: {
|
||||
Dictionary d;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::OBJECT: {
|
||||
Object *obj = p_variant.get_validated_object();
|
||||
|
||||
if (p_allow_classes && obj) {
|
||||
Dictionary d;
|
||||
List<PropertyInfo> property_list;
|
||||
obj->get_property_list(&property_list);
|
||||
|
||||
d["type"] = obj->get_class();
|
||||
Dictionary p;
|
||||
for (const PropertyInfo &P : property_list) {
|
||||
if (P.usage & PROPERTY_USAGE_STORAGE) {
|
||||
if (P.name == "script" && !p_allow_scripts) {
|
||||
continue;
|
||||
}
|
||||
p[P.name] = from_native(obj->get(P.name), PASS_ARG);
|
||||
}
|
||||
}
|
||||
d["properties"] = p;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} else {
|
||||
Dictionary nil;
|
||||
nil[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return nil;
|
||||
}
|
||||
} break;
|
||||
case Variant::CALLABLE:
|
||||
case Variant::SIGNAL: {
|
||||
Dictionary nil;
|
||||
nil[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return nil;
|
||||
} break;
|
||||
case Variant::DICTIONARY: {
|
||||
Dictionary d = p_variant;
|
||||
List<Variant> keys;
|
||||
d.get_key_list(&keys);
|
||||
bool all_strings = true;
|
||||
for (const Variant &K : keys) {
|
||||
if (K.get_type() != Variant::STRING) {
|
||||
all_strings = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_strings) {
|
||||
Dictionary ret_dict;
|
||||
for (const Variant &K : keys) {
|
||||
ret_dict[K] = from_native(d[K], PASS_ARG);
|
||||
}
|
||||
return ret_dict;
|
||||
} else {
|
||||
Dictionary ret;
|
||||
Array pairs;
|
||||
for (const Variant &K : keys) {
|
||||
Dictionary pair;
|
||||
pair["key"] = from_native(K, PASS_ARG);
|
||||
pair["value"] = from_native(d[K], PASS_ARG);
|
||||
pairs.push_back(pair);
|
||||
}
|
||||
ret["pairs"] = pairs;
|
||||
ret[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return ret;
|
||||
}
|
||||
} break;
|
||||
case Variant::ARRAY: {
|
||||
Array arr = p_variant;
|
||||
Array ret;
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
ret.push_back(from_native(arr[i], PASS_ARG));
|
||||
}
|
||||
return ret;
|
||||
} break;
|
||||
case Variant::PACKED_BYTE_ARRAY: {
|
||||
Dictionary d;
|
||||
PackedByteArray arr = p_variant;
|
||||
Array values;
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
values.push_back(arr[i]);
|
||||
}
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::PACKED_INT32_ARRAY: {
|
||||
Dictionary d;
|
||||
PackedInt32Array arr = p_variant;
|
||||
Array values;
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
values.push_back(arr[i]);
|
||||
}
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
|
||||
} break;
|
||||
case Variant::PACKED_INT64_ARRAY: {
|
||||
Dictionary d;
|
||||
PackedInt64Array arr = p_variant;
|
||||
Array values;
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
values.push_back(arr[i]);
|
||||
}
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::PACKED_FLOAT32_ARRAY: {
|
||||
Dictionary d;
|
||||
PackedFloat32Array arr = p_variant;
|
||||
Array values;
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
values.push_back(arr[i]);
|
||||
}
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::PACKED_FLOAT64_ARRAY: {
|
||||
Dictionary d;
|
||||
PackedFloat64Array arr = p_variant;
|
||||
Array values;
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
values.push_back(arr[i]);
|
||||
}
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::PACKED_STRING_ARRAY: {
|
||||
Dictionary d;
|
||||
PackedStringArray arr = p_variant;
|
||||
Array values;
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
values.push_back(arr[i]);
|
||||
}
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::PACKED_VECTOR2_ARRAY: {
|
||||
Dictionary d;
|
||||
PackedVector2Array arr = p_variant;
|
||||
Array values;
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
Vector2 v = arr[i];
|
||||
values.push_back(v.x);
|
||||
values.push_back(v.y);
|
||||
}
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::PACKED_VECTOR3_ARRAY: {
|
||||
Dictionary d;
|
||||
PackedVector3Array arr = p_variant;
|
||||
Array values;
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
Vector3 v = arr[i];
|
||||
values.push_back(v.x);
|
||||
values.push_back(v.y);
|
||||
values.push_back(v.z);
|
||||
}
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::PACKED_COLOR_ARRAY: {
|
||||
Dictionary d;
|
||||
PackedColorArray arr = p_variant;
|
||||
Array values;
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
Color v = arr[i];
|
||||
values.push_back(v.r);
|
||||
values.push_back(v.g);
|
||||
values.push_back(v.b);
|
||||
values.push_back(v.a);
|
||||
}
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
case Variant::PACKED_VECTOR4_ARRAY: {
|
||||
Dictionary d;
|
||||
PackedVector4Array arr = p_variant;
|
||||
Array values;
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
Vector4 v = arr[i];
|
||||
values.push_back(v.x);
|
||||
values.push_back(v.y);
|
||||
values.push_back(v.z);
|
||||
values.push_back(v.w);
|
||||
}
|
||||
d[VALUES] = values;
|
||||
d[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return d;
|
||||
} break;
|
||||
default: {
|
||||
ERR_PRINT(vformat("Unhandled conversion from native Variant type '%s' to JSON.", Variant::get_type_name(p_variant.get_type())));
|
||||
} break;
|
||||
}
|
||||
|
||||
Dictionary nil;
|
||||
nil[GDTYPE] = Variant::get_type_name(p_variant.get_type());
|
||||
return nil;
|
||||
}
|
||||
|
||||
Variant JSON::to_native(const Variant &p_json, bool p_allow_classes, bool p_allow_scripts) {
|
||||
switch (p_json.get_type()) {
|
||||
case Variant::BOOL: {
|
||||
return p_json;
|
||||
} break;
|
||||
case Variant::INT: {
|
||||
return p_json;
|
||||
} break;
|
||||
case Variant::FLOAT: {
|
||||
return p_json;
|
||||
} break;
|
||||
case Variant::STRING: {
|
||||
return p_json;
|
||||
} break;
|
||||
case Variant::STRING_NAME: {
|
||||
return p_json;
|
||||
} break;
|
||||
case Variant::CALLABLE: {
|
||||
return p_json;
|
||||
} break;
|
||||
case Variant::DICTIONARY: {
|
||||
Dictionary d = p_json;
|
||||
if (d.has(GDTYPE)) {
|
||||
// Specific Godot Variant types serialized to JSON.
|
||||
String type = d[GDTYPE];
|
||||
if (type == Variant::get_type_name(Variant::VECTOR2)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
ERR_FAIL_COND_V(values.size() != 2, Variant());
|
||||
Vector2 v;
|
||||
v.x = values[0];
|
||||
v.y = values[1];
|
||||
return v;
|
||||
} else if (type == Variant::get_type_name(Variant::VECTOR2I)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
ERR_FAIL_COND_V(values.size() != 2, Variant());
|
||||
Vector2i v;
|
||||
v.x = values[0];
|
||||
v.y = values[1];
|
||||
return v;
|
||||
} else if (type == Variant::get_type_name(Variant::RECT2)) {
|
||||
ERR_FAIL_COND_V(!d.has("position"), Variant());
|
||||
ERR_FAIL_COND_V(!d.has("size"), Variant());
|
||||
Rect2 r;
|
||||
r.position = to_native(d["position"]);
|
||||
r.size = to_native(d["size"]);
|
||||
return r;
|
||||
} else if (type == Variant::get_type_name(Variant::RECT2I)) {
|
||||
ERR_FAIL_COND_V(!d.has("position"), Variant());
|
||||
ERR_FAIL_COND_V(!d.has("size"), Variant());
|
||||
Rect2i r;
|
||||
r.position = to_native(d["position"]);
|
||||
r.size = to_native(d["size"]);
|
||||
return r;
|
||||
} else if (type == Variant::get_type_name(Variant::VECTOR3)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
ERR_FAIL_COND_V(values.size() != 3, Variant());
|
||||
Vector3 v;
|
||||
v.x = values[0];
|
||||
v.y = values[1];
|
||||
v.z = values[2];
|
||||
return v;
|
||||
} else if (type == Variant::get_type_name(Variant::VECTOR3I)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
ERR_FAIL_COND_V(values.size() != 3, Variant());
|
||||
Vector3i v;
|
||||
v.x = values[0];
|
||||
v.y = values[1];
|
||||
v.z = values[2];
|
||||
return v;
|
||||
} else if (type == Variant::get_type_name(Variant::TRANSFORM2D)) {
|
||||
ERR_FAIL_COND_V(!d.has("x"), Variant());
|
||||
ERR_FAIL_COND_V(!d.has("y"), Variant());
|
||||
ERR_FAIL_COND_V(!d.has("origin"), Variant());
|
||||
Transform2D t;
|
||||
t[0] = to_native(d["x"]);
|
||||
t[1] = to_native(d["y"]);
|
||||
t[2] = to_native(d["origin"]);
|
||||
return t;
|
||||
} else if (type == Variant::get_type_name(Variant::VECTOR4)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
ERR_FAIL_COND_V(values.size() != 4, Variant());
|
||||
Vector4 v;
|
||||
v.x = values[0];
|
||||
v.y = values[1];
|
||||
v.z = values[2];
|
||||
v.w = values[3];
|
||||
return v;
|
||||
} else if (type == Variant::get_type_name(Variant::VECTOR4I)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
ERR_FAIL_COND_V(values.size() != 4, Variant());
|
||||
Vector4i v;
|
||||
v.x = values[0];
|
||||
v.y = values[1];
|
||||
v.z = values[2];
|
||||
v.w = values[3];
|
||||
return v;
|
||||
} else if (type == Variant::get_type_name(Variant::PLANE)) {
|
||||
ERR_FAIL_COND_V(!d.has("normal"), Variant());
|
||||
ERR_FAIL_COND_V(!d.has("d"), Variant());
|
||||
Plane p;
|
||||
p.normal = to_native(d["normal"]);
|
||||
p.d = d["d"];
|
||||
return p;
|
||||
} else if (type == Variant::get_type_name(Variant::QUATERNION)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
ERR_FAIL_COND_V(values.size() != 4, Variant());
|
||||
Quaternion v;
|
||||
v.x = values[0];
|
||||
v.y = values[1];
|
||||
v.z = values[2];
|
||||
v.w = values[3];
|
||||
return v;
|
||||
} else if (type == Variant::get_type_name(Variant::AABB)) {
|
||||
ERR_FAIL_COND_V(!d.has("position"), Variant());
|
||||
ERR_FAIL_COND_V(!d.has("size"), Variant());
|
||||
AABB r;
|
||||
r.position = to_native(d["position"]);
|
||||
r.size = to_native(d["size"]);
|
||||
return r;
|
||||
} else if (type == Variant::get_type_name(Variant::BASIS)) {
|
||||
ERR_FAIL_COND_V(!d.has("x"), Variant());
|
||||
ERR_FAIL_COND_V(!d.has("y"), Variant());
|
||||
ERR_FAIL_COND_V(!d.has("z"), Variant());
|
||||
Basis b;
|
||||
b.set_column(0, to_native(d["x"]));
|
||||
b.set_column(1, to_native(d["y"]));
|
||||
b.set_column(2, to_native(d["z"]));
|
||||
return b;
|
||||
} else if (type == Variant::get_type_name(Variant::TRANSFORM3D)) {
|
||||
ERR_FAIL_COND_V(!d.has("basis"), Variant());
|
||||
ERR_FAIL_COND_V(!d.has("origin"), Variant());
|
||||
Transform3D t;
|
||||
t.basis = to_native(d["basis"]);
|
||||
t.origin = to_native(d["origin"]);
|
||||
return t;
|
||||
} else if (type == Variant::get_type_name(Variant::PROJECTION)) {
|
||||
ERR_FAIL_COND_V(!d.has("x"), Variant());
|
||||
ERR_FAIL_COND_V(!d.has("y"), Variant());
|
||||
ERR_FAIL_COND_V(!d.has("z"), Variant());
|
||||
ERR_FAIL_COND_V(!d.has("w"), Variant());
|
||||
Projection p;
|
||||
p[0] = to_native(d["x"]);
|
||||
p[1] = to_native(d["y"]);
|
||||
p[2] = to_native(d["z"]);
|
||||
p[3] = to_native(d["w"]);
|
||||
return p;
|
||||
} else if (type == Variant::get_type_name(Variant::COLOR)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
ERR_FAIL_COND_V(values.size() != 4, Variant());
|
||||
Color c;
|
||||
c.r = values[0];
|
||||
c.g = values[1];
|
||||
c.b = values[2];
|
||||
c.a = values[3];
|
||||
return c;
|
||||
} else if (type == Variant::get_type_name(Variant::NODE_PATH)) {
|
||||
ERR_FAIL_COND_V(!d.has("path"), Variant());
|
||||
NodePath np = d["path"];
|
||||
return np;
|
||||
} else if (type == Variant::get_type_name(Variant::STRING_NAME)) {
|
||||
ERR_FAIL_COND_V(!d.has("name"), Variant());
|
||||
StringName s = d["name"];
|
||||
return s;
|
||||
} else if (type == Variant::get_type_name(Variant::OBJECT)) {
|
||||
ERR_FAIL_COND_V(!d.has("type"), Variant());
|
||||
ERR_FAIL_COND_V(!d.has("properties"), Variant());
|
||||
|
||||
ERR_FAIL_COND_V(!p_allow_classes, Variant());
|
||||
|
||||
String obj_type = d["type"];
|
||||
bool is_script = obj_type == "Script" || ClassDB::is_parent_class(obj_type, "Script");
|
||||
ERR_FAIL_COND_V(!p_allow_scripts && is_script, Variant());
|
||||
Object *obj = ClassDB::instantiate(obj_type);
|
||||
ERR_FAIL_NULL_V(obj, Variant());
|
||||
|
||||
Dictionary p = d["properties"];
|
||||
|
||||
List<Variant> keys;
|
||||
p.get_key_list(&keys);
|
||||
|
||||
for (const Variant &K : keys) {
|
||||
String property = K;
|
||||
Variant value = to_native(p[K], PASS_ARG);
|
||||
obj->set(property, value);
|
||||
}
|
||||
|
||||
Variant v(obj);
|
||||
|
||||
return v;
|
||||
} else if (type == Variant::get_type_name(Variant::DICTIONARY)) {
|
||||
ERR_FAIL_COND_V(!d.has("pairs"), Variant());
|
||||
Array pairs = d["pairs"];
|
||||
Dictionary r;
|
||||
for (int i = 0; i < pairs.size(); i++) {
|
||||
Dictionary p = pairs[i];
|
||||
ERR_CONTINUE(!p.has("key"));
|
||||
ERR_CONTINUE(!p.has("value"));
|
||||
r[to_native(p["key"], PASS_ARG)] = to_native(p["value"]);
|
||||
}
|
||||
return r;
|
||||
} else if (type == Variant::get_type_name(Variant::ARRAY)) {
|
||||
ERR_PRINT(vformat("Unexpected Array with '%s' key. Arrays are supported natively.", GDTYPE));
|
||||
} else if (type == Variant::get_type_name(Variant::PACKED_BYTE_ARRAY)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
PackedByteArray pbarr;
|
||||
pbarr.resize(values.size());
|
||||
for (int i = 0; i < pbarr.size(); i++) {
|
||||
pbarr.write[i] = values[i];
|
||||
}
|
||||
return pbarr;
|
||||
} else if (type == Variant::get_type_name(Variant::PACKED_INT32_ARRAY)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
PackedInt32Array arr;
|
||||
arr.resize(values.size());
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
arr.write[i] = values[i];
|
||||
}
|
||||
return arr;
|
||||
} else if (type == Variant::get_type_name(Variant::PACKED_INT64_ARRAY)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
PackedInt64Array arr;
|
||||
arr.resize(values.size());
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
arr.write[i] = values[i];
|
||||
}
|
||||
return arr;
|
||||
} else if (type == Variant::get_type_name(Variant::PACKED_FLOAT32_ARRAY)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
PackedFloat32Array arr;
|
||||
arr.resize(values.size());
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
arr.write[i] = values[i];
|
||||
}
|
||||
return arr;
|
||||
} else if (type == Variant::get_type_name(Variant::PACKED_FLOAT64_ARRAY)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
PackedFloat64Array arr;
|
||||
arr.resize(values.size());
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
arr.write[i] = values[i];
|
||||
}
|
||||
return arr;
|
||||
} else if (type == Variant::get_type_name(Variant::PACKED_STRING_ARRAY)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
PackedStringArray arr;
|
||||
arr.resize(values.size());
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
arr.write[i] = values[i];
|
||||
}
|
||||
return arr;
|
||||
} else if (type == Variant::get_type_name(Variant::PACKED_VECTOR2_ARRAY)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
ERR_FAIL_COND_V(values.size() % 2 != 0, Variant());
|
||||
PackedVector2Array arr;
|
||||
arr.resize(values.size() / 2);
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
arr.write[i] = Vector2(values[i * 2 + 0], values[i * 2 + 1]);
|
||||
}
|
||||
return arr;
|
||||
} else if (type == Variant::get_type_name(Variant::PACKED_VECTOR3_ARRAY)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
ERR_FAIL_COND_V(values.size() % 3 != 0, Variant());
|
||||
PackedVector3Array arr;
|
||||
arr.resize(values.size() / 3);
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
arr.write[i] = Vector3(values[i * 3 + 0], values[i * 3 + 1], values[i * 3 + 2]);
|
||||
}
|
||||
return arr;
|
||||
} else if (type == Variant::get_type_name(Variant::PACKED_COLOR_ARRAY)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
ERR_FAIL_COND_V(values.size() % 4 != 0, Variant());
|
||||
PackedColorArray arr;
|
||||
arr.resize(values.size() / 4);
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
arr.write[i] = Color(values[i * 4 + 0], values[i * 4 + 1], values[i * 4 + 2], values[i * 4 + 3]);
|
||||
}
|
||||
return arr;
|
||||
} else if (type == Variant::get_type_name(Variant::PACKED_VECTOR4_ARRAY)) {
|
||||
ERR_FAIL_COND_V(!d.has(VALUES), Variant());
|
||||
Array values = d[VALUES];
|
||||
ERR_FAIL_COND_V(values.size() % 4 != 0, Variant());
|
||||
PackedVector4Array arr;
|
||||
arr.resize(values.size() / 4);
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
arr.write[i] = Vector4(values[i * 4 + 0], values[i * 4 + 1], values[i * 4 + 2], values[i * 4 + 3]);
|
||||
}
|
||||
return arr;
|
||||
} else {
|
||||
return Variant();
|
||||
}
|
||||
} else {
|
||||
// Regular dictionary with string keys.
|
||||
List<Variant> keys;
|
||||
d.get_key_list(&keys);
|
||||
Dictionary r;
|
||||
for (const Variant &K : keys) {
|
||||
r[K] = to_native(d[K], PASS_ARG);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
} break;
|
||||
case Variant::ARRAY: {
|
||||
Array arr = p_json;
|
||||
Array ret;
|
||||
ret.resize(arr.size());
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
ret[i] = to_native(arr[i], PASS_ARG);
|
||||
}
|
||||
return ret;
|
||||
} break;
|
||||
default: {
|
||||
ERR_PRINT(vformat("Unhandled conversion from JSON type '%s' to native Variant type.", Variant::get_type_name(p_json.get_type())));
|
||||
return Variant();
|
||||
}
|
||||
}
|
||||
|
||||
return Variant();
|
||||
}
|
||||
|
||||
#undef GDTYPE
|
||||
#undef VALUES
|
||||
#undef PASS_ARG
|
||||
////
|
||||
|
||||
////////////
|
||||
|
||||
|
@ -94,9 +94,6 @@ public:
|
||||
void set_data(const Variant &p_data);
|
||||
inline int get_error_line() const { return err_line; }
|
||||
inline String get_error_message() const { return err_str; }
|
||||
|
||||
static Variant from_native(const Variant &p_variant, bool p_allow_classes = false, bool p_allow_scripts = false);
|
||||
static Variant to_native(const Variant &p_json, bool p_allow_classes = false, bool p_allow_scripts = false);
|
||||
};
|
||||
|
||||
class ResourceFormatLoaderJSON : public ResourceFormatLoader {
|
||||
|
@ -84,7 +84,11 @@ void Logger::log_error(const char *p_function, const char *p_file, int p_line, c
|
||||
err_details = p_code;
|
||||
}
|
||||
|
||||
logf_error("%s: %s\n", err_type, err_details);
|
||||
if (p_editor_notify) {
|
||||
logf_error("%s: %s\n", err_type, err_details);
|
||||
} else {
|
||||
logf_error("USER %s: %s\n", err_type, err_details);
|
||||
}
|
||||
logf_error(" at: %s (%s:%i)\n", p_function, p_file, p_line);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
class PackedDataContainer : public Resource {
|
||||
GDCLASS(PackedDataContainer, Resource);
|
||||
|
||||
enum : uint32_t {
|
||||
enum {
|
||||
TYPE_DICT = 0xFFFFFFFF,
|
||||
TYPE_ARRAY = 0xFFFFFFFE,
|
||||
};
|
||||
|
@ -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));
|
||||
|
@ -32,12 +32,12 @@
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/io/file_access.h"
|
||||
|
||||
PacketPeerDTLS *(*PacketPeerDTLS::_create)(bool p_notify_postinitialize) = nullptr;
|
||||
PacketPeerDTLS *(*PacketPeerDTLS::_create)() = nullptr;
|
||||
bool PacketPeerDTLS::available = false;
|
||||
|
||||
PacketPeerDTLS *PacketPeerDTLS::create(bool p_notify_postinitialize) {
|
||||
PacketPeerDTLS *PacketPeerDTLS::create() {
|
||||
if (_create) {
|
||||
return _create(p_notify_postinitialize);
|
||||
return _create();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ class PacketPeerDTLS : public PacketPeer {
|
||||
GDCLASS(PacketPeerDTLS, PacketPeer);
|
||||
|
||||
protected:
|
||||
static PacketPeerDTLS *(*_create)(bool p_notify_postinitialize);
|
||||
static PacketPeerDTLS *(*_create)();
|
||||
static void _bind_methods();
|
||||
|
||||
static bool available;
|
||||
@ -57,7 +57,7 @@ public:
|
||||
virtual void disconnect_from_peer() = 0;
|
||||
virtual Status get_status() const = 0;
|
||||
|
||||
static PacketPeerDTLS *create(bool p_notify_postinitialize = true);
|
||||
static PacketPeerDTLS *create();
|
||||
static bool is_available();
|
||||
|
||||
PacketPeerDTLS() {}
|
||||
|
@ -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_path", "alignment", "key", "encrypt_directory"), &PCKPacker::pck_start, DEFVAL(32), DEFVAL("0000000000000000000000000000000000000000000000000000000000000000"), DEFVAL(false));
|
||||
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("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_pck_path, int p_alignment, const String &p_key, bool p_encrypt_directory) {
|
||||
Error PCKPacker::pck_start(const String &p_file, 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_pck_path, int p_alignment, const Stri
|
||||
}
|
||||
enc_dir = p_encrypt_directory;
|
||||
|
||||
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) + ".");
|
||||
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) + ".");
|
||||
|
||||
alignment = p_alignment;
|
||||
|
||||
@ -106,7 +106,7 @@ Error PCKPacker::pck_start(const String &p_pck_path, int p_alignment, const Stri
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error PCKPacker::add_file(const String &p_pck_path, const String &p_src, bool p_encrypt) {
|
||||
Error PCKPacker::add_file(const String &p_file, 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_pck_path, const String &p_src, bool p_
|
||||
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_pck_path.simplify_path();
|
||||
pf.path = p_file.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_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 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 flush(bool p_verbose = false);
|
||||
|
||||
PCKPacker() {}
|
||||
|
@ -814,7 +814,7 @@ bool PList::load_string(const String &p_string, String &r_err_out) {
|
||||
}
|
||||
|
||||
PackedByteArray PList::save_asn1() const {
|
||||
if (root.is_null()) {
|
||||
if (root == nullptr) {
|
||||
ERR_FAIL_V_MSG(PackedByteArray(), "PList: Invalid PList, no root node.");
|
||||
}
|
||||
size_t size = root->get_asn1_size(1);
|
||||
@ -848,7 +848,7 @@ PackedByteArray PList::save_asn1() const {
|
||||
}
|
||||
|
||||
String PList::save_text() const {
|
||||
if (root.is_null()) {
|
||||
if (root == nullptr) {
|
||||
ERR_FAIL_V_MSG(String(), "PList: Invalid PList, no root node.");
|
||||
}
|
||||
|
||||
|
@ -40,12 +40,12 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void Resource::emit_changed() {
|
||||
if (ResourceLoader::is_within_load() && !Thread::is_main_thread()) {
|
||||
ResourceLoader::resource_changed_emit(this);
|
||||
return;
|
||||
if (ResourceLoader::is_within_load() && MessageQueue::get_main_singleton() != MessageQueue::get_singleton() && !MessageQueue::get_singleton()->is_flushing()) {
|
||||
// Let the connection happen on the call queue, later, since signals are not thread-safe.
|
||||
call_deferred("emit_signal", CoreStringName(changed));
|
||||
} else {
|
||||
emit_signal(CoreStringName(changed));
|
||||
}
|
||||
|
||||
emit_signal(CoreStringName(changed));
|
||||
}
|
||||
|
||||
void Resource::_resource_path_changed() {
|
||||
@ -60,33 +60,33 @@ void Resource::set_path(const String &p_path, bool p_take_over) {
|
||||
p_take_over = false; // Can't take over an empty path
|
||||
}
|
||||
|
||||
{
|
||||
MutexLock lock(ResourceCache::lock);
|
||||
ResourceCache::lock.lock();
|
||||
|
||||
if (!path_cache.is_empty()) {
|
||||
ResourceCache::resources.erase(path_cache);
|
||||
}
|
||||
if (!path_cache.is_empty()) {
|
||||
ResourceCache::resources.erase(path_cache);
|
||||
}
|
||||
|
||||
path_cache = "";
|
||||
path_cache = "";
|
||||
|
||||
Ref<Resource> existing = ResourceCache::get_ref(p_path);
|
||||
Ref<Resource> existing = ResourceCache::get_ref(p_path);
|
||||
|
||||
if (existing.is_valid()) {
|
||||
if (p_take_over) {
|
||||
existing->path_cache = String();
|
||||
ResourceCache::resources.erase(p_path);
|
||||
} else {
|
||||
ERR_FAIL_MSG("Another resource is loaded from path '" + p_path + "' (possible cyclic resource inclusion).");
|
||||
}
|
||||
}
|
||||
|
||||
path_cache = p_path;
|
||||
|
||||
if (!path_cache.is_empty()) {
|
||||
ResourceCache::resources[path_cache] = this;
|
||||
if (existing.is_valid()) {
|
||||
if (p_take_over) {
|
||||
existing->path_cache = String();
|
||||
ResourceCache::resources.erase(p_path);
|
||||
} else {
|
||||
ResourceCache::lock.unlock();
|
||||
ERR_FAIL_MSG("Another resource is loaded from path '" + p_path + "' (possible cyclic resource inclusion).");
|
||||
}
|
||||
}
|
||||
|
||||
path_cache = p_path;
|
||||
|
||||
if (!path_cache.is_empty()) {
|
||||
ResourceCache::resources[path_cache] = this;
|
||||
}
|
||||
ResourceCache::lock.unlock();
|
||||
|
||||
_resource_path_changed();
|
||||
}
|
||||
|
||||
@ -96,7 +96,6 @@ 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() {
|
||||
@ -167,29 +166,28 @@ bool Resource::editor_can_reload_from_file() {
|
||||
}
|
||||
|
||||
void Resource::connect_changed(const Callable &p_callable, uint32_t p_flags) {
|
||||
if (ResourceLoader::is_within_load() && !Thread::is_main_thread()) {
|
||||
ResourceLoader::resource_changed_connect(this, p_callable, p_flags);
|
||||
if (ResourceLoader::is_within_load() && MessageQueue::get_main_singleton() != MessageQueue::get_singleton() && !MessageQueue::get_singleton()->is_flushing()) {
|
||||
// Let the check and connection happen on the call queue, later, since signals are not thread-safe.
|
||||
callable_mp(this, &Resource::connect_changed).call_deferred(p_callable, p_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_connected(CoreStringName(changed), p_callable) || p_flags & CONNECT_REFERENCE_COUNTED) {
|
||||
connect(CoreStringName(changed), p_callable, p_flags);
|
||||
}
|
||||
}
|
||||
|
||||
void Resource::disconnect_changed(const Callable &p_callable) {
|
||||
if (ResourceLoader::is_within_load() && !Thread::is_main_thread()) {
|
||||
ResourceLoader::resource_changed_disconnect(this, p_callable);
|
||||
if (ResourceLoader::is_within_load() && MessageQueue::get_main_singleton() != MessageQueue::get_singleton() && !MessageQueue::get_singleton()->is_flushing()) {
|
||||
// Let the check and disconnection happen on the call queue, later, since signals are not thread-safe.
|
||||
callable_mp(this, &Resource::disconnect_changed).call_deferred(p_callable);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_connected(CoreStringName(changed), p_callable)) {
|
||||
disconnect(CoreStringName(changed), p_callable);
|
||||
}
|
||||
}
|
||||
|
||||
void Resource::reset_state() {
|
||||
GDVIRTUAL_CALL(_reset_state);
|
||||
}
|
||||
|
||||
Error Resource::copy_from(const Ref<Resource> &p_resource) {
|
||||
@ -418,15 +416,21 @@ void Resource::_take_over_path(const String &p_path) {
|
||||
}
|
||||
|
||||
RID Resource::get_rid() const {
|
||||
RID ret;
|
||||
if (!GDVIRTUAL_CALL(_get_rid, ret)) {
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
if (_get_extension() && _get_extension()->get_rid) {
|
||||
ret = RID::from_uint64(_get_extension()->get_rid(_get_extension_instance()));
|
||||
if (get_script_instance()) {
|
||||
Callable::CallError ce;
|
||||
RID ret = get_script_instance()->callp(SNAME("_get_rid"), nullptr, 0, ce);
|
||||
if (ce.error == Callable::CallError::CALL_OK && ret.is_valid()) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
if (_get_extension() && _get_extension()->get_rid) {
|
||||
RID ret = RID::from_uint64(_get_extension()->get_rid(_get_extension_instance()));
|
||||
if (ret.is_valid()) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return RID();
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
@ -488,18 +492,20 @@ void Resource::set_as_translation_remapped(bool p_remapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLock lock(ResourceCache::lock);
|
||||
ResourceCache::lock.lock();
|
||||
|
||||
if (p_remapped) {
|
||||
ResourceLoader::remapped_list.add(&remapped_list);
|
||||
} else {
|
||||
ResourceLoader::remapped_list.remove(&remapped_list);
|
||||
}
|
||||
|
||||
ResourceCache::lock.unlock();
|
||||
}
|
||||
|
||||
#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());
|
||||
@ -509,11 +515,9 @@ 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()];
|
||||
@ -523,16 +527,13 @@ String Resource::get_id_for_path(const String &p_path) const {
|
||||
ResourceCache::path_cache_lock.read_unlock();
|
||||
return "";
|
||||
}
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
#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);
|
||||
@ -540,12 +541,6 @@ 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);
|
||||
@ -563,10 +558,11 @@ void Resource::_bind_methods() {
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_name"), "set_name", "get_name");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "resource_scene_unique_id", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_scene_unique_id", "get_scene_unique_id");
|
||||
|
||||
MethodInfo get_rid_bind("_get_rid");
|
||||
get_rid_bind.return_val.type = Variant::RID;
|
||||
|
||||
::ClassDB::add_virtual_method(get_class_static(), get_rid_bind, true, Vector<String>(), true);
|
||||
GDVIRTUAL_BIND(_setup_local_to_scene);
|
||||
GDVIRTUAL_BIND(_get_rid);
|
||||
GDVIRTUAL_BIND(_reset_state);
|
||||
GDVIRTUAL_BIND(_set_path_cache, "path");
|
||||
}
|
||||
|
||||
Resource::Resource() :
|
||||
@ -577,13 +573,14 @@ Resource::~Resource() {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLock lock(ResourceCache::lock);
|
||||
ResourceCache::lock.lock();
|
||||
// Only unregister from the cache if this is the actual resource listed there.
|
||||
// (Other resources can have the same value in `path_cache` if loaded with `CACHE_IGNORE`.)
|
||||
HashMap<String, Resource *>::Iterator E = ResourceCache::resources.find(path_cache);
|
||||
if (likely(E && E->value == this)) {
|
||||
ResourceCache::resources.remove(E);
|
||||
}
|
||||
ResourceCache::lock.unlock();
|
||||
}
|
||||
|
||||
HashMap<String, Resource *> ResourceCache::resources;
|
||||
@ -612,21 +609,19 @@ void ResourceCache::clear() {
|
||||
}
|
||||
|
||||
bool ResourceCache::has(const String &p_path) {
|
||||
Resource **res = nullptr;
|
||||
lock.lock();
|
||||
|
||||
{
|
||||
MutexLock mutex_lock(lock);
|
||||
Resource **res = resources.getptr(p_path);
|
||||
|
||||
res = resources.getptr(p_path);
|
||||
|
||||
if (res && (*res)->get_reference_count() == 0) {
|
||||
// This resource is in the process of being deleted, ignore its existence.
|
||||
(*res)->path_cache = String();
|
||||
resources.erase(p_path);
|
||||
res = nullptr;
|
||||
}
|
||||
if (res && (*res)->get_reference_count() == 0) {
|
||||
// This resource is in the process of being deleted, ignore its existence.
|
||||
(*res)->path_cache = String();
|
||||
resources.erase(p_path);
|
||||
res = nullptr;
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
|
||||
if (!res) {
|
||||
return false;
|
||||
}
|
||||
@ -636,27 +631,28 @@ bool ResourceCache::has(const String &p_path) {
|
||||
|
||||
Ref<Resource> ResourceCache::get_ref(const String &p_path) {
|
||||
Ref<Resource> ref;
|
||||
{
|
||||
MutexLock mutex_lock(lock);
|
||||
Resource **res = resources.getptr(p_path);
|
||||
lock.lock();
|
||||
|
||||
if (res) {
|
||||
ref = Ref<Resource>(*res);
|
||||
}
|
||||
Resource **res = resources.getptr(p_path);
|
||||
|
||||
if (res && !ref.is_valid()) {
|
||||
// This resource is in the process of being deleted, ignore its existence
|
||||
(*res)->path_cache = String();
|
||||
resources.erase(p_path);
|
||||
res = nullptr;
|
||||
}
|
||||
if (res) {
|
||||
ref = Ref<Resource>(*res);
|
||||
}
|
||||
|
||||
if (res && !ref.is_valid()) {
|
||||
// This resource is in the process of being deleted, ignore its existence
|
||||
(*res)->path_cache = String();
|
||||
resources.erase(p_path);
|
||||
res = nullptr;
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
void ResourceCache::get_cached_resources(List<Ref<Resource>> *p_resources) {
|
||||
MutexLock mutex_lock(lock);
|
||||
lock.lock();
|
||||
|
||||
LocalVector<String> to_remove;
|
||||
|
||||
@ -676,9 +672,14 @@ void ResourceCache::get_cached_resources(List<Ref<Resource>> *p_resources) {
|
||||
for (const String &E : to_remove) {
|
||||
resources.erase(E);
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
int ResourceCache::get_cached_resource_count() {
|
||||
MutexLock mutex_lock(lock);
|
||||
return resources.size();
|
||||
lock.lock();
|
||||
int rc = resources.size();
|
||||
lock.unlock();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -87,11 +87,6 @@ protected:
|
||||
virtual void reset_local_to_scene();
|
||||
GDVIRTUAL0(_setup_local_to_scene);
|
||||
|
||||
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
|
||||
@ -147,9 +142,11 @@ 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();
|
||||
|
@ -845,29 +845,14 @@ Error ResourceLoaderBinary::load() {
|
||||
}
|
||||
}
|
||||
|
||||
if (ClassDB::has_property(res->get_class_name(), name)) {
|
||||
if (value.get_type() == Variant::ARRAY) {
|
||||
Array set_array = value;
|
||||
bool is_get_valid = false;
|
||||
Variant get_value = res->get(name, &is_get_valid);
|
||||
if (is_get_valid && get_value.get_type() == Variant::ARRAY) {
|
||||
Array get_array = get_value;
|
||||
if (!set_array.is_same_typed(get_array)) {
|
||||
value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value.get_type() == Variant::DICTIONARY) {
|
||||
Dictionary set_dict = value;
|
||||
bool is_get_valid = false;
|
||||
Variant get_value = res->get(name, &is_get_valid);
|
||||
if (is_get_valid && get_value.get_type() == Variant::DICTIONARY) {
|
||||
Dictionary get_dict = get_value;
|
||||
if (!set_dict.is_same_typed(get_dict)) {
|
||||
value = Dictionary(set_dict, get_dict.get_typed_key_builtin(), get_dict.get_typed_key_class_name(), get_dict.get_typed_key_script(),
|
||||
get_dict.get_typed_value_builtin(), get_dict.get_typed_value_class_name(), get_dict.get_typed_value_script());
|
||||
}
|
||||
if (value.get_type() == Variant::ARRAY) {
|
||||
Array set_array = value;
|
||||
bool is_get_valid = false;
|
||||
Variant get_value = res->get(name, &is_get_valid);
|
||||
if (is_get_valid && get_value.get_type() == Variant::ARRAY) {
|
||||
Array get_array = get_value;
|
||||
if (!set_array.is_same_typed(get_array)) {
|
||||
value = Array(set_array, get_array.get_typed_builtin(), get_array.get_typed_class_name(), get_array.get_typed_script());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2079,8 +2064,6 @@ void ResourceFormatSaverBinaryInstance::_find_resources(const Variant &p_variant
|
||||
|
||||
case Variant::DICTIONARY: {
|
||||
Dictionary d = p_variant;
|
||||
_find_resources(d.get_typed_key_script());
|
||||
_find_resources(d.get_typed_value_script());
|
||||
List<Variant> keys;
|
||||
d.get_key_list(&keys);
|
||||
for (const Variant &E : keys) {
|
||||
|
@ -35,8 +35,6 @@
|
||||
#include "core/os/os.h"
|
||||
#include "core/variant/variant_parser.h"
|
||||
|
||||
ResourceFormatImporterLoadOnStartup ResourceImporter::load_on_startup = nullptr;
|
||||
|
||||
bool ResourceFormatImporter::SortImporterByName::operator()(const Ref<ResourceImporter> &p_a, const Ref<ResourceImporter> &p_b) const {
|
||||
return p_a->get_importer_name() < p_b->get_importer_name();
|
||||
}
|
||||
@ -139,20 +137,6 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
|
||||
}
|
||||
|
||||
Ref<Resource> ResourceFormatImporter::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
// When loading a resource on startup, we use the load_on_startup callback,
|
||||
// which executes the loading in the EditorFileSystem. It can reimport
|
||||
// the resource and retry the load, allowing the resource to be loaded
|
||||
// even if it is not yet imported.
|
||||
if (ResourceImporter::load_on_startup != nullptr) {
|
||||
return ResourceImporter::load_on_startup(this, p_path, r_error, p_use_sub_threads, r_progress, p_cache_mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
return load_internal(p_path, r_error, p_use_sub_threads, r_progress, p_cache_mode, false);
|
||||
}
|
||||
|
||||
Ref<Resource> ResourceFormatImporter::load_internal(const String &p_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode, bool p_silence_errors) {
|
||||
PathAndType pat;
|
||||
Error err = _get_path_and_type(p_path, pat);
|
||||
|
||||
@ -164,13 +148,6 @@ Ref<Resource> ResourceFormatImporter::load_internal(const String &p_path, Error
|
||||
return Ref<Resource>();
|
||||
}
|
||||
|
||||
if (p_silence_errors) {
|
||||
// Note: Some importers do not create files in the .godot folder, so we need to check if the path is empty.
|
||||
if (!pat.path.is_empty() && !FileAccess::exists(pat.path)) {
|
||||
return Ref<Resource>();
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Resource> res = ResourceLoader::_load(pat.path, p_path, pat.type, p_cache_mode, r_error, p_use_sub_threads, r_progress);
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
@ -387,23 +364,6 @@ ResourceUID::ID ResourceFormatImporter::get_resource_uid(const String &p_path) c
|
||||
return pat.uid;
|
||||
}
|
||||
|
||||
Error ResourceFormatImporter::get_resource_import_info(const String &p_path, StringName &r_type, ResourceUID::ID &r_uid, String &r_import_group_file) const {
|
||||
PathAndType pat;
|
||||
Error err = _get_path_and_type(p_path, pat);
|
||||
|
||||
if (err == OK) {
|
||||
r_type = pat.type;
|
||||
r_uid = pat.uid;
|
||||
r_import_group_file = pat.group_file;
|
||||
} else {
|
||||
r_type = "";
|
||||
r_uid = ResourceUID::INVALID_ID;
|
||||
r_import_group_file = "";
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
Variant ResourceFormatImporter::get_resource_metadata(const String &p_path) const {
|
||||
PathAndType pat;
|
||||
Error err = _get_path_and_type(p_path, pat);
|
||||
@ -507,7 +467,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, pat.metadata)) { //importer thinks this is not valid
|
||||
if (!importers[i]->are_import_settings_valid(p_path)) { //importer thinks this is not valid
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user