Compare commits

..

No commits in common. "development" and "fix/justfile-export_templates" have entirely different histories.

7672 changed files with 823765 additions and 2026765 deletions

View file

@ -1,5 +0,0 @@
((c-mode . ((mode . c++)))
(c++-mode . ((mode . clang-format-on-save)))
(nil . ((projectile-project-compilation-cmd . "just build")
(projectile-project-run-cmd . "engine/bin/godot.linuxbsd.editor.dev.x86_64.llvm --path project")
(projectile-project-configure-cmd . "engine/bin/godot.linuxbsd.editor.dev.x86_64.llvm --path project -e"))))

12
.gitignore vendored
View file

@ -6,13 +6,9 @@
config.log
.sconf_temp
# build artifacts
*.o
compile_commands.json
engine/.github
project/.godot
build/
__pycache__
# general-purpose cache folder (used by e.g clangd)
.cache
build/PROJECT.pck
build/PROJECT.x86_64
build/PROJECT.exe
build.zip

3
.gitmodules vendored
View file

@ -0,0 +1,3 @@
[submodule "engine"]
path = engine
url = https://github.com/godotengine/godot.git

View file

@ -1,9 +1,6 @@
# If you change this file, please format all files of the codebase as part of your PR:
# pre-commit run clang-format --all
# 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).
# chosen value in case the base style changes (last sync: Clang 17.0.6).
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign
@ -13,45 +10,39 @@ AlignAfterOpenBracket: DontAlign
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCompound: false
# AlignFunctionPointers: false
# PadOperators: true
# AlignConsecutiveBitFields:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCompound: false
# AlignFunctionPointers: false
# PadOperators: false
# AlignConsecutiveDeclarations:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCompound: false
# AlignFunctionPointers: false
# PadOperators: false
# AlignConsecutiveMacros:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCompound: false
# AlignFunctionPointers: false
# PadOperators: false
# AlignConsecutiveShortCaseStatements:
# Enabled: false
# AcrossEmptyLines: false
# AcrossComments: false
# AlignCaseColons: false
AlignEscapedNewlines: DontAlign # Aligning leads to long diffs
# AlignEscapedNewlines: Right
AlignOperands: DontAlign
AlignTrailingComments:
Kind: Never
OverEmptyLines: 0
# AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
# AllowBreakBeforeNoexceptSpecifier: Never
# AllowShortBlocksOnASingleLine: Never
# AllowShortCaseLabelsOnASingleLine: false
# AllowShortCompoundRequirementOnASingleLine: true
# AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
# AllowShortIfStatementsOnASingleLine: Never
@ -61,10 +52,8 @@ AllowShortFunctionsOnASingleLine: Inline
# AlwaysBreakAfterReturnType: None
# AlwaysBreakBeforeMultilineStrings: false
# AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- _ALWAYS_INLINE_
- _FORCE_INLINE_
- _NO_INLINE_
# AttributeMacros:
# - __capability
# BinPackArguments: true
# BinPackParameters: true
# BitFieldColonSpacing: Both
@ -87,8 +76,7 @@ AttributeMacros:
# SplitEmptyFunction: true
# SplitEmptyRecord: true
# SplitEmptyNamespace: true
# BreakAdjacentStringLiterals: true
# BreakAfterAttributes: Leave
# BreakAfterAttributes: Never
# BreakAfterJavaFieldAnnotations: false
# BreakArrays: true
# BreakBeforeBinaryOperators: None
@ -177,7 +165,6 @@ PackConstructorInitializers: NextLine
# PenaltyBreakComment: 300
# PenaltyBreakFirstLessLess: 120
# PenaltyBreakOpenParenthesis: 0
# PenaltyBreakScopeResolution: 500
# PenaltyBreakString: 1000
# PenaltyBreakTemplateDeclaration: 10
# PenaltyExcessCharacter: 1000000
@ -194,7 +181,6 @@ RemoveSemicolon: true
# RequiresExpressionIndentation: OuterScope
# SeparateDefinitionBlocks: Leave
# ShortNamespaceLines: 1
# SkipMacroDefinitionBody: false
# SortIncludes: CaseSensitive
# SortJavaStaticImport: Before
# SortUsingDeclarations: LexicographicNumeric
@ -216,7 +202,6 @@ RemoveSemicolon: true
# AfterFunctionDefinitionName: false
# AfterIfMacros: true
# AfterOverloadedOperator: false
# AfterPlacementOperator: true
# AfterRequiresInClause: false
# AfterRequiresInExpression: false
# BeforeNonEmptyParentheses: false

View file

@ -1,25 +1,19 @@
# If you change this file, please format all files of the codebase as part of your PR:
# pre-commit run --hook-stage manual clang-tidy --all
Checks:
- -*
- bugprone-use-after-move
- modernize-deprecated-headers
- cppcoreguidelines-pro-type-member-init
- modernize-redundant-void-arg
- modernize-use-bool-literals
# - modernize-use-default-member-init # TODO Re-activate
- modernize-use-default-member-init
- modernize-use-nullptr
- readability-braces-around-statements
- readability-redundant-member-init
- readability-operators-representation
HeaderFileExtensions: ["", h, hh, hpp, hxx, inc, glsl]
ImplementationFileExtensions: [c, cc, cpp, cxx, m, mm, java]
HeaderFilterRegex: (core|doc|drivers|editor|main|modules|platform|scene|servers|tests)/
FormatStyle: file
CheckOptions:
modernize-deprecated-headers.CheckHeaderFile: true
cppcoreguidelines-pro-type-member-init.IgnoreArrays: true
cppcoreguidelines-pro-type-member-init.UseAssignment: true
modernize-use-bool-literals.IgnoreMacros: false
modernize-use-default-member-init.IgnoreMacros: false
modernize-use-default-member-init.UseAssignment: true
readability-operators-representation.BinaryOperators: "&&;&=;&;|;~;!;!=;||;|=;^;^="
readability-operators-representation.OverloadedOperators: "&&;&=;&;|;~;!;!=;||;|=;^;^="

View file

@ -72,18 +72,3 @@ e06d83860d798b6766b23d6eae48557387a7db85
# Style: Replace header guards with `#pragma once`
324512e11c1b7663c3cf47bec6ddbe65c6b8db2b
# Style: Don't right-align escaped newlines
c5df0cb82bc539eff7dcfb2add99d60771fc50c5
# Style: Convert `*.gen.inc` to `*.gen.h`
7dae5da1982f4a55ba91557814905faef9ce461b
# Move RenderingServer enums to a dedicated RenderingServerEnums (`RSE`) namespace
f5a290ac462765afca34e64dd39f883511510147
# Style: Add `class_db.h` includes explicitly
e380a417526c11f15a9ddb3997292409b10da2af
# Move DisplayServer enums and typedefs to DisplayServerEnums
a447ac95ec170ee117c2eae55f1bfff0d0cf0dce

View file

@ -9,7 +9,7 @@ thirdparty/* linguist-vendored
*.bat eol=crlf
*.sln eol=crlf
*.csproj eol=crlf
misc/msvs/* eol=crlf
misc/msvs/*.template eol=crlf
# And some test files where the EOL matters
*.test.txt -text

View file

@ -1,290 +0,0 @@
# Lines starting with '#' are comments.
# Each line is a file pattern followed by one or more owners.
# Owners can be @users, @org/teams or emails.
# Core
/core/ @godotengine/core
/core/crypto/ @godotengine/network
/core/debugger/ @godotengine/debugger
/core/extension/ @godotengine/gdextension
/core/input/ @godotengine/input
# Doc
/doc/ @godotengine/documentation
/doc/translations/ @godotengine/i18n
# 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
## Input
/drivers/sdl/ @godotengine/input
## Rendering
/drivers/d3d12/ @godotengine/rendering
/drivers/dummy/ @godotengine/rendering
/drivers/egl/ @godotengine/rendering
/drivers/gles3/ @godotengine/rendering
/drivers/metal/ @godotengine/rendering
/drivers/spirv-reflect/ @godotengine/rendering
/drivers/vulkan/ @godotengine/rendering
## OS
/drivers/apple*/ @godotengine/macos
/drivers/unix/ @godotengine/linux-bsd
/drivers/windows/ @godotengine/windows
## Misc
/drivers/register_driver_types.* @godotengine/buildsystem
/drivers/accesskit/ @godotengine/buildsystem
/drivers/png/ @godotengine/asset-pipeline
# Editor
/editor/ @godotengine/editor
/editor/animation/ @godotengine/editor @godotengine/animation
/editor/audio/ @godotengine/editor @godotengine/audio
/editor/debugger/ @godotengine/editor @godotengine/debugger
/editor/doc/ @godotengine/editor @godotengine/documentation
/editor/gui/ @godotengine/editor @godotengine/gui-nodes
/editor/import/ @godotengine/editor @godotengine/asset-pipeline
/editor/scene/2d/ @godotengine/editor @godotengine/2d-nodes
/editor/scene/2d/physics/ @godotengine/editor @godotengine/physics
/editor/scene/3d/ @godotengine/editor @godotengine/3d-nodes
/editor/scene/3d/physics/ @godotengine/editor @godotengine/physics
/editor/scene/gui/ @godotengine/editor @godotengine/gui-nodes
/editor/script/ @godotengine/editor @godotengine/script-editor
/editor/shader/ @godotengine/editor @godotengine/script-editor @godotengine/shaders
/editor/themes/ @godotengine/editor @godotengine/gui-nodes
/editor/translations/ @godotengine/i18n
# Main
/main/ @godotengine/core
# Misc
/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/interactive_music/editor/ @godotengine/audio @godotengine/editor
/modules/mp3/ @godotengine/audio
/modules/mp3/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/theora/editor/ @godotengine/audio @godotengine/editor
/modules/vorbis/ @godotengine/audio
/modules/vorbis/doc_classes/ @godotengine/audio @godotengine/documentation
## Import
/modules/astcenc/ @godotengine/asset-pipeline
/modules/basis_universal/ @godotengine/asset-pipeline
/modules/bcdec/ @godotengine/asset-pipeline
/modules/betsy/ @godotengine/asset-pipeline
/modules/bmp/ @godotengine/asset-pipeline
/modules/cvtt/ @godotengine/asset-pipeline
/modules/dds/ @godotengine/asset-pipeline
/modules/dds/tests/ @godotengine/asset-pipeline @godotengine/tests
/modules/etcpak/ @godotengine/asset-pipeline
/modules/fbx/ @godotengine/asset-pipeline
/modules/fbx/doc_classes/ @godotengine/asset-pipeline @godotengine/documentation
/modules/fbx/editor/ @godotengine/asset-pipeline @godotengine/editor
/modules/gltf/ @godotengine/asset-pipeline
/modules/gltf/doc_classes/ @godotengine/asset-pipeline @godotengine/documentation
/modules/gltf/editor/ @godotengine/asset-pipeline @godotengine/editor
/modules/gltf/tests/ @godotengine/asset-pipeline @godotengine/tests
/modules/hdr/ @godotengine/asset-pipeline
/modules/jpg/ @godotengine/asset-pipeline
/modules/ktx/ @godotengine/asset-pipeline
/modules/squish/ @godotengine/asset-pipeline
/modules/svg/ @godotengine/asset-pipeline
/modules/tga/ @godotengine/asset-pipeline
/modules/tinyexr/ @godotengine/asset-pipeline
/modules/webp/ @godotengine/asset-pipeline
## 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/multiplayer/editor/ @godotengine/network @godotengine/editor
/modules/multiplayer/tests/ @godotengine/network @godotengine/tests
/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
/modules/websocket/editor/ @godotengine/network @godotengine/editor
## Physics
/modules/godot_physics_2d/ @godotengine/physics
/modules/godot_physics_3d/ @godotengine/physics
/modules/jolt_physics/ @godotengine/physics @godotengine/jolt-physics
## Rendering
/modules/glslang/ @godotengine/rendering
/modules/lightmapper_rd/ @godotengine/rendering
/modules/meshoptimizer/ @godotengine/rendering
/modules/raycast/ @godotengine/rendering
/modules/vhacd/ @godotengine/rendering
/modules/xatlas_unwrap/ @godotengine/rendering
## Scripting
/modules/gdscript/ @godotengine/gdscript
/modules/gdscript/doc_classes/ @godotengine/gdscript @godotengine/documentation
/modules/gdscript/editor/ @godotengine/gdscript @godotengine/script-editor
/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/editor/ @godotengine/dotnet @godotengine/script-editor
## Text
/modules/freetype/ @godotengine/buildsystem
/modules/msdfgen/ @godotengine/buildsystem
/modules/text_server_adv/ @godotengine/gui-nodes
/modules/text_server_adv/doc_classes/ @godotengine/gui-nodes @godotengine/documentation
/modules/text_server_fb/ @godotengine/gui-nodes
/modules/text_server_fb/doc_classes/ @godotengine/gui-nodes @godotengine/documentation
## XR
/modules/camera/ @godotengine/xr
/modules/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/openxr/editor/ @godotengine/xr @godotengine/editor
/modules/webxr/ @godotengine/xr
/modules/webxr/doc_classes/ @godotengine/xr @godotengine/documentation
## Misc
/modules/register_module_types.* @godotengine/buildsystem
/modules/csg/ @godotengine/3d-nodes
/modules/csg/doc_classes/ @godotengine/3d-nodes @godotengine/documentation
/modules/csg/editor/ @godotengine/3d-nodes @godotengine/editor
/modules/csg/tests/ @godotengine/3d-nodes @godotengine/tests
/modules/gridmap/ @godotengine/3d-nodes
/modules/gridmap/doc_classes/ @godotengine/3d-nodes @godotengine/documentation
/modules/gridmap/editor/ @godotengine/3d-nodes @godotengine/editor
/modules/navigation_2d/ @godotengine/navigation
/modules/navigation_2d/editor/ @godotengine/navigation @godotengine/editor
/modules/navigation_3d/ @godotengine/navigation
/modules/navigation_3d/editor/ @godotengine/navigation @godotengine/editor
/modules/noise/ @godotengine/core
/modules/noise/doc_classes/ @godotengine/core @godotengine/documentation
/modules/noise/editor/ @godotengine/core @godotengine/editor
/modules/noise/tests/ @godotengine/core @godotengine/tests
/modules/objectdb_profiler/ @godotengine/debugger
/modules/objectdb_profiler/editor/ @godotengine/debugger @godotengine/editor
/modules/regex/ @godotengine/core
/modules/regex/doc_classes/ @godotengine/core @godotengine/documentation
/modules/regex/tests/ @godotengine/core @godotengine/tests
/modules/zip/ @godotengine/core
/modules/zip/doc_classes/ @godotengine/core @godotengine/documentation
/modules/zip/tests/ @godotengine/core @godotengine/tests
# Platform
/platform/register_platform_apis.* @godotengine/buildsystem
/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/visionos/ @godotengine/xr
/platform/visionos/doc_classes/ @godotengine/xr @godotengine/documentation
/platform/web/ @godotengine/web
/platform/web/doc_classes/ @godotengine/web @godotengine/documentation
/platform/windows/ @godotengine/windows
/platform/windows/doc_classes/ @godotengine/windows @godotengine/documentation
# Scene
/scene/property_* @godotengine/buildsystem
/scene/register_scene_types.* @godotengine/buildsystem
/scene/scene_string_names.* @godotengine/buildsystem
/scene/2d/ @godotengine/2d-nodes
/scene/2d/navigation/ @godotengine/2d-nodes @godotengine/navigation
/scene/2d/physics/ @godotengine/2d-nodes @godotengine/physics
/scene/3d/ @godotengine/3d-nodes
/scene/3d/navigation/ @godotengine/3d-nodes @godotengine/navigation
/scene/3d/physics/ @godotengine/3d-nodes @godotengine/physics
/scene/3d/xr/ @godotengine/3d-nodes @godotengine/xr
/scene/animation/ @godotengine/animation
/scene/audio/ @godotengine/audio
/scene/debugger/ @godotengine/debugger
/scene/gui/ @godotengine/gui-nodes
/scene/main/ @godotengine/core
/scene/resources/* @godotengine/gui-nodes
/scene/resources/2d/ @godotengine/2d-nodes
/scene/resources/2d/skeleton/ @godotengine/2d-nodes @godotengine/animation
/scene/resources/3d/ @godotengine/3d-nodes
/scene/resources/animated* @godotengine/animation
/scene/resources/animation* @godotengine/animation
/scene/resources/audio* @godotengine/audio
/scene/resources/bone* @godotengine/animation
/scene/resources/font* @godotengine/gui-nodes
/scene/resources/physics* @godotengine/physics
/scene/resources/shader* @godotengine/shaders
/scene/resources/skeleton* @godotengine/animation
/scene/resources/text_* @godotengine/gui-nodes
/scene/resources/visual_shader* @godotengine/shaders
/scene/theme/ @godotengine/gui-nodes
# Servers
/servers/nav_heap.* @godotengine/navigation
/servers/register_server_types.* @godotengine/buildsystem
/servers/server_wrap_* @godotengine/buildsystem
/servers/audio/ @godotengine/audio
/servers/camera/ @godotengine/xr
/servers/debugger/ @godotengine/debugger
/servers/display/ @godotengine/rendering
/servers/movie_writer/ @godotengine/rendering
/servers/navigation_2d/ @godotengine/navigation
/servers/navigation_3d/ @godotengine/navigation
/servers/physics_2d/ @godotengine/physics
/servers/physics_3d/ @godotengine/physics
/servers/rendering/ @godotengine/rendering
/servers/text/ @godotengine/gui-nodes
/servers/xr/ @godotengine/xr
# Tests
/tests/ @godotengine/tests
# Thirdparty
/thirdparty/ @godotengine/buildsystem
/thirdparty/jolt_physics/ @godotengine/buildsystem @godotengine/jolt-physics
# Buildsystem (After everything to catch all)
/*.* @godotengine/buildsystem
*.py @godotengine/buildsystem
SConstruct @godotengine/buildsystem
SCsub @godotengine/buildsystem

View file

@ -1,72 +0,0 @@
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: |
- Reproducible in: 4.3.dev [d76c1d0e5], 4.2.stable, 4.2.dev5 and later 4.2 snapshots.
- Not reproducible in: 4.1.3.stable, 4.2.dev4 and earlier 4.2 snapshots.
validations:
required: true
- type: input
attributes:
label: System information
description: |
- Specify the OS version, and when relevant hardware information.
- For issues that are likely OS-specific and/or graphics-related, please specify the CPU model and architecture.
- For graphics-related issues, specify the GPU model, driver version, and the rendering backend (GLES2, GLES3, Vulkan).
- **Bug reports not including the required information may be closed at the maintainers' discretion.** If in doubt, always include all the requested information; it's better to include too much information than not enough information.
- **Starting from Godot 4.1, you can copy this information to your clipboard by using *Help > Copy System Info* at the top of the editor window.**
placeholder: Windows 10 - Godot v4.0.3.stable - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 970 (nvidia, 510.85.02) - Intel Core i7-10700KF CPU @ 3.80GHz (16 Threads)
validations:
required: true
- type: textarea
attributes:
label: Issue description
description: |
Describe your issue briefly. What doesn't work, and how do you expect it to work instead?
You can include images or videos with drag and drop, and format code blocks or logs with <code>\`\`\`</code> tags, on separate lines before and after the text. (Use <code>\`\`\`gdscript</code> to add GDScript syntax highlighting.)
Please do not add code examples or error messages as screenshots, but as text, this helps searching for issues and testing the code. If you are reporting a bug in the editor interface, like the script editor, please provide both a screenshot *and* the text of the code to help with testing.
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: |
List of steps or sample code that reproduces the issue. Having reproducible issues is a prerequisite for contributors to be able to solve them.
If you include a minimal reproduction project below, you can detail how to use it here.
validations:
required: true
- type: textarea
attributes:
label: 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

View file

@ -1,14 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Godot proposals
url: https://github.com/godotengine/godot-proposals
about: Please submit feature proposals on the Godot proposals repository, not here.
- name: Godot documentation repository
url: https://github.com/godotengine/godot-docs
about: Please report issues with documentation on the Godot documentation repository, not here.
- name: Godot community channels
url: https://godotengine.org/community
about: Please ask for technical support on one of the other community channels, not here.

View file

@ -1,6 +0,0 @@
<!--
Please target the `master` branch. We will take care of backporting relevant fixes to older versions.
Before submitting, please read our checklist for new contributors:
https://contributing.godotengine.org/en/latest/engine/introduction.html#checklist-for-new-contributors
-->

View file

@ -1,20 +0,0 @@
name: Download Godot artifact
description: Download the Godot artifact.
inputs:
name:
description: The artifact name.
default: ${{ github.job }}
path:
description: The path to download and extract to.
required: true
default: ./
runs:
using: composite
steps:
- name: Download Godot Artifact
uses: actions/download-artifact@v4
with:
name: ${{ inputs.name }}
path: ${{ inputs.path }}

View file

@ -1,42 +0,0 @@
name: Build Godot
description: Build Godot with the provided options.
inputs:
target:
description: Build target (editor, template_release, template_debug).
default: editor
type: choice
options: [editor, template_debug, template_release]
platform:
description: Target platform.
type: string
scons-flags:
description: Additional SCons flags.
type: string
scons-cache:
description: The SCons cache path.
default: ${{ github.workspace }}/.scons_cache/
type: string
runs:
using: composite
steps:
- name: SCons Build
shell: sh
run: |
echo "Building with flags:" platform=${{ inputs.platform }} target=${{ inputs.target }} ${{ inputs.scons-flags }} "cache_path=${{ inputs.scons-cache }}" redirect_build_objects=no
if [ "${{ inputs.target }}" != "editor" ]; then
# Ensure we don't include editor code in export template builds.
rm -rf editor
fi
if [ "${{ github.event.number }}" != "" ]; then
# Set build identifier with pull request number if available. This is displayed throughout the editor.
export BUILD_NAME="gh-${{ github.event.number }}"
else
export BUILD_NAME="gh"
fi
scons platform=${{ inputs.platform }} target=${{ inputs.target }} ${{ inputs.scons-flags }} "cache_path=${{ inputs.scons-cache }}" redirect_build_objects=no
ls -l bin/

View file

@ -1,39 +0,0 @@
name: Restore Godot build cache
description: Restore Godot build cache.
inputs:
cache-name:
description: The cache base name (job name by default).
default: ${{ github.job }}
scons-cache:
description: The SCons cache path.
default: ${{ github.workspace }}/.scons_cache/
runs:
using: composite
steps:
- name: Restore default cache
uses: actions/cache/restore@v4
id: cache-ping
with:
path: ${{ inputs.scons-cache }}
key: ${{ inputs.cache-name }}|${{ github.event.repository.default_branch }}|${{ github.sha }}
restore-keys: ${{ inputs.cache-name }}|${{ github.event.repository.default_branch }}
- name: Log default cache files
if: steps.cache-ping.outputs.cache-matched-key && github.ref_name != github.event.repository.default_branch
shell: sh
run: find "${{ inputs.scons-cache }}" >> redundant.txt
# This is done after pulling the default cache so that PRs can integrate any potential changes
# from the default branch without conflicting with whatever local changes were already made.
- name: Restore local cache
uses: actions/cache/restore@v4
if: github.ref_name != github.event.repository.default_branch
with:
path: ${{ inputs.scons-cache }}
key: ${{ inputs.cache-name }}|${{ github.ref_name }}|${{ github.sha }}
restore-keys: ${{ inputs.cache-name }}|${{ github.ref_name }}
- name: Store unix timestamp
shell: sh
run: echo "CACHE_TIMESTAMP=$(date +%s)" >> $GITHUB_ENV

View file

@ -1,22 +0,0 @@
name: Save Godot build cache
description: Save Godot build cache.
inputs:
cache-name:
description: The cache base name (job name by default).
default: ${{ github.job }}
scons-cache:
description: The SCons cache path.
default: ${{ github.workspace }}/.scons_cache/
runs:
using: composite
steps:
- name: Purge files before timestamp
shell: sh
run: misc/scripts/purge_cache.py ${{ env.CACHE_TIMESTAMP }} "${{ inputs.scons-cache }}"
- name: Save SCons cache directory
uses: actions/cache/save@v4
with:
path: ${{ inputs.scons-cache }}
key: ${{ inputs.cache-name }}|${{ github.ref_name }}|${{ github.sha }}

View file

@ -1,33 +0,0 @@
name: Godot hash compatibility test
description: Check if methods with given hashes used by the older GDExtensions still can be loaded with given Godot version.
inputs:
bin:
description: Path to the Godot binary.
required: true
type: string
reftags:
description: Reference tags of Godot versions to check (comma separated).
required: true
type: string
runs:
using: composite
steps:
- name: Extract GDExtension interface
shell: sh
run: |
${{ inputs.bin }} --headless --dump-gdextension-interface
mkdir tests/compatibility_test/src/deps/
mv gdextension_interface.h tests/compatibility_test/src/deps/
- name: Build minimal GDExtension
shell: sh
run: scons --directory=./tests/compatibility_test
- name: Download reference GDExtension API JSON and try to load it
shell: sh
env:
GODOT4_BIN: ${{ inputs.bin }}
REFTAGS: ${{ inputs.reftags }}
run: ./tests/compatibility_test/run_compatibility_test.py

View file

@ -1,20 +0,0 @@
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
steps:
- name: Test 3-to-4 conversion
shell: sh
run: |
mkdir converter_test
cd converter_test
touch project.godot
../${{ inputs.bin }} --headless --validate-conversion-3to4
cd ..
rm converter_test -rf

View file

@ -1,40 +0,0 @@
name: Build godot-cpp
description: Build godot-cpp with the provided options.
inputs:
bin:
description: Path to the Godot binary.
required: true
type: string
scons-flags:
description: Additional SCons flags.
type: string
scons-cache:
description: The SCons cache path.
default: ${{ github.workspace }}/.scons_cache/
type: string
godot-cpp-branch:
description: The godot-cpp branch.
default: master
type: string
runs:
using: composite
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
repository: godotengine/godot-cpp
ref: ${{ inputs.godot-cpp-branch }}
path: godot-cpp
- name: Extract API
shell: sh
run: ${{ inputs.bin }} --headless --dump-gdextension-interface --dump-extension-api
- name: SCons Build
shell: sh
env:
SCONS_CACHE: ${{ inputs.scons-cache }}
run: scons --directory=./godot-cpp/test "gdextension_dir=${{ github.workspace }}" ${{ inputs.scons-flags }}

View file

@ -1,35 +0,0 @@
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
python-arch:
description: The Python architecture.
default: x64
scons-version:
description: The SCons version to use.
default: 4.10.1
runs:
using: composite
steps:
- name: Set up Python 3.x
uses: actions/setup-python@v5
with:
# Semantic version range syntax or exact version of a Python version.
python-version: ${{ inputs.python-version }}
# Optional - x64 or x86 architecture, defaults to x64.
architecture: ${{ inputs.python-arch }}
- name: Setup SCons
shell: bash
run: |
python -c "import sys; print(sys.version)"
python -m pip install scons==${{ inputs.scons-version }}
scons --version
- name: Setup problem matchers
shell: bash
run: echo ::add-matcher::misc/utility/problem-matchers.json

View file

@ -1,55 +0,0 @@
name: Export Godot project
description: Export a test Godot project.
inputs:
bin:
description: The path to the Godot executable
required: true
runs:
using: composite
steps:
- name: Import resources and export project
shell: sh
run: |
git clone --depth=1 https://github.com/godotengine/godot-tests.git /tmp/godot-tests
echo "Exporting project for Linux (PCK)"
${{ inputs.bin }} --headless --path /tmp/godot-tests/tests/test_project/ --export-pack "Linux" /tmp/test_project.pck 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
echo "Exporting project for Linux (ZIP)"
${{ inputs.bin }} --headless --path /tmp/godot-tests/tests/test_project/ --export-pack "Linux" /tmp/test_project.zip 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
echo "Exporting project for Linux as dedicated server (PCK)"
${{ inputs.bin }} --headless --path /tmp/godot-tests/tests/test_project/ --export-pack "Linux Server" /tmp/test_project_server.pck 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
- name: Run project files from folder
shell: sh
run: |
xvfb-run ${{ inputs.bin }} --path /tmp/godot-tests/tests/test_project/ --language fr --resolution 64x64 --write-movie /tmp/test_project_folder.png --quit 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
${{ inputs.bin }} --headless --path /tmp/godot-tests/tests/test_project/ --quit 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
- name: Run exported project PCK/ZIP
shell: sh
run: |
xvfb-run ${{ inputs.bin }} --main-pack /tmp/test_project.pck --language fr --resolution 64x64 --write-movie /tmp/test_project_pck.png --quit 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
xvfb-run ${{ inputs.bin }} --main-pack /tmp/test_project.zip --language fr --resolution 64x64 --write-movie /tmp/test_project_zip.png --quit 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
# Headless mode is implied for dedicated server PCKs.
${{ inputs.bin }} --main-pack /tmp/test_project_server.pck --quit 2>&1 | tee log.txt || true
GODOT_CHECK_CI_LOG_ALL_ERRORS=1 misc/scripts/check_ci_log.py log.txt
echo "Checking whether video output from project folder and exported project match..."
md5sum /tmp/test_project*.png | md5sum --check
echo "Checking whether audio output from project folder and exported project match..."
md5sum /tmp/test_project*.wav | md5sum --check

View file

@ -1,45 +0,0 @@
name: Test Godot project
description: Run the test Godot project.
inputs:
bin:
description: The path to the Godot executable
required: true
runs:
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
shell: sh
run: |
wget https://github.com/godotengine/regression-test-project/archive/4.0.zip
unzip 4.0.zip
mv "regression-test-project-4.0" "test_project"
# Editor is quite complicated piece of software, so it is easy to introduce bug here.
- name: Open and close editor (Headless)
shell: sh
run: |
xvfb-run ${{ inputs.bin }} --headless --import --path test_project 2>&1 | tee sanitizers_log.txt || true
misc/scripts/check_ci_log.py sanitizers_log.txt
- name: Open and close editor (Vulkan)
shell: sh
run: |
xvfb-run ${{ inputs.bin }} --audio-driver Dummy --import --path test_project 2>&1 | tee sanitizers_log.txt || true
misc/scripts/check_ci_log.py sanitizers_log.txt
- name: Open and close editor (GLES3)
shell: sh
run: |
DRI_PRIME=0 xvfb-run ${{ inputs.bin }} --audio-driver Dummy --rendering-driver opengl3 --import --path test_project 2>&1 | tee sanitizers_log.txt || true
misc/scripts/check_ci_log.py sanitizers_log.txt
# Run test project
- name: Run project
shell: sh
run: |
xvfb-run ${{ inputs.bin }} 40 --audio-driver Dummy --path test_project 2>&1 | tee sanitizers_log.txt || true
misc/scripts/check_ci_log.py sanitizers_log.txt

View file

@ -1,22 +0,0 @@
name: Upload Godot artifact
description: Upload the Godot artifact.
inputs:
name:
description: The artifact name.
default: ${{ github.job }}
path:
description: The path to upload.
required: true
default: bin/*
runs:
using: composite
steps:
- name: Upload Godot Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.name }}
path: ${{ inputs.path }}
# Default is 90 days.
retention-days: 60

View file

@ -1,16 +0,0 @@
# We lack a convenient means of gathering *all* the changes when specializations are passed, so
# a catch-all variable is the easiest workaround.
everything:
- "**"
# Determines if build actions should occur after static checks are ran. Broadly speaking, these
# files changing would result in SCons rebuilding the engine, or are otherwise pertinent to the
# buildsystem itself.
sources:
- .github/{actions,workflows}/*.yml
- "**/{SConstruct,SCsub,*.py}"
- "**/*.{h,hpp,hh,hxx,c,cpp,cc,cxx,m,mm,inc,glsl}"
- modules/mono/**/*.{cs,csproj,sln,props,targets}
- platform/android/java/{gradle*,**/*.{jar,java,kt,gradle}}
- platform/web/{package{,-lock}.json,js/**/*.js}
- tests/**

View file

@ -1,117 +0,0 @@
name: 🤖 Android Builds
on:
workflow_call:
workflow_dispatch:
# Global Settings
env:
SCONS_FLAGS: >-
dev_mode=yes
module_text_server_fb_enabled=yes
swappy=yes
jobs:
build-android:
runs-on: ubuntu-24.04
name: ${{ matrix.name }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- name: Editor (target=editor)
cache-name: android-editor
target: editor
scons-flags: >-
arch=arm64
production=yes
- name: Template arm32 (target=template_debug, arch=arm32)
cache-name: android-template-arm32
target: template_debug
scons-flags: arch=arm32
- name: Template arm64 (target=template_debug, arch=arm64)
cache-name: android-template-arm64
target: template_debug
scons-flags: arch=arm64
steps:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: recursive
- name: Set up Java 17
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 17
- name: Restore Godot build cache
uses: ./.github/actions/godot-cache-restore
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Setup Python and SCons
uses: ./.github/actions/godot-deps
- name: Download Swappy
run: python ./misc/scripts/install_swappy_android.py
- name: Compilation
uses: ./.github/actions/godot-build
with:
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }}
platform: android
target: ${{ matrix.target }}
- name: Save Godot build cache
uses: ./.github/actions/godot-cache-save
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Generate Godot templates
if: matrix.target == 'template_debug'
run: |
cd platform/android/java
./gradlew generateGodotTemplates
cd ../../..
ls -l bin/
- name: Generate Godot editor
if: matrix.target == 'editor'
run: |
cd platform/android/java
./gradlew generateGodotEditor
./gradlew generateGodotHorizonOSEditor
./gradlew generateGodotPicoOSEditor
cd ../../..
ls -l bin/android_editor_builds/
# Separate different editors for multiple artifacts
mkdir horizonos
mv bin/android_editor_builds/*-horizonos-* horizonos
mkdir picoos
mv bin/android_editor_builds/*-picoos-* picoos
- name: Upload artifact
uses: ./.github/actions/upload-artifact
with:
name: ${{ matrix.cache-name }}
- name: Upload artifact (Horizon OS)
if: matrix.target == 'editor'
uses: ./.github/actions/upload-artifact
with:
name: ${{ matrix.cache-name }}-horizonos
path: horizonos
- name: Upload artifact (PICO OS)
if: matrix.target == 'editor'
uses: ./.github/actions/upload-artifact
with:
name: ${{ matrix.cache-name }}-picoos
path: picoos

View file

@ -1,49 +0,0 @@
name: 🍏 iOS Builds
on:
workflow_call:
workflow_dispatch:
# Global Settings
env:
SCONS_FLAGS: >-
dev_mode=yes
module_text_server_fb_enabled=yes
debug_symbols=no
jobs:
ios-template:
# From https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#choosing-github-hosted-runners
runs-on: macos-latest
name: Template (target=template_release)
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: recursive
# From https://github.com/actions/runner-images/blob/main/images/macos
- name: Select Xcode 26
run: sudo xcode-select -s /Applications/Xcode_26.0.1.app
- name: Restore Godot build cache
uses: ./.github/actions/godot-cache-restore
continue-on-error: true
- name: Setup Python and SCons
uses: ./.github/actions/godot-deps
- name: Compilation (arm64)
uses: ./.github/actions/godot-build
with:
scons-flags: ${{ env.SCONS_FLAGS }}
platform: ios
target: template_release
- name: Save Godot build cache
uses: ./.github/actions/godot-cache-save
continue-on-error: true
- name: Upload artifact
uses: ./.github/actions/upload-artifact

View file

@ -1,284 +0,0 @@
name: 🐧 Linux Builds
on:
workflow_call:
inputs:
changed-files:
description: A list of changed files.
required: true
type: string
workflow_dispatch:
# Global Settings
env:
SCONS_FLAGS: >-
dev_mode=yes
module_text_server_fb_enabled=yes
GODOT_CPP_BRANCH: 4.5
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
ASAN_OPTIONS: color=always:print_suppressions=1:suppressions=${{ github.workspace }}/misc/error_suppressions/asan.txt
LSAN_OPTIONS: color=always:print_suppressions=1:suppressions=${{ github.workspace }}/misc/error_suppressions/lsan.txt
TSAN_OPTIONS: color=always:print_suppressions=1:suppressions=${{ github.workspace }}/misc/error_suppressions/tsan.txt
UBSAN_OPTIONS: color=always:print_suppressions=1:suppressions=${{ github.workspace }}/misc/error_suppressions/ubsan.txt
jobs:
build-linux:
# Stay one LTS before latest to increase portability of Linux artifacts.
runs-on: ubuntu-22.04
name: ${{ matrix.name }}
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
include:
- name: Editor w/ Mono (target=editor)
cache-name: linux-editor-mono
target: editor
scons-flags: module_mono_enabled=yes compiledb=yes
bin: ./bin/godot.linuxbsd.editor.x86_64.mono
build-mono: true
doc-test: true
proj-conv: true
proj-export: true
api-compat: true
artifact: true
# Validate godot-cpp compatibility on one arbitrary editor build.
godot-cpp: true
clang-tidy: true
- name: Editor with doubles and GCC sanitizers (target=editor, dev_build=yes, scu_build=yes, precision=double, use_asan=yes, use_ubsan=yes, linker=mold)
cache-name: linux-editor-double-sanitizers
target: editor
# Debug symbols disabled as they're huge on this build and we hit the 14 GB limit for runners.
scons-flags: >-
dev_build=yes
scu_build=yes
debug_symbols=no
precision=double
use_asan=yes
use_ubsan=yes
linker=mold
bin: ./bin/godot.linuxbsd.editor.dev.double.x86_64.san
proj-test: true
- name: Editor with clang sanitizers (target=editor, dev_build=yes, use_asan=yes, use_ubsan=yes, use_llvm=yes, linker=lld)
cache-name: linux-editor-llvm-sanitizers
target: editor
scons-flags: >-
dev_build=yes
use_asan=yes
use_ubsan=yes
use_llvm=yes
linker=lld
bin: ./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san
# Test our oldest supported SCons/Python versions on one arbitrary editor build.
legacy-scons: true
- name: Editor with ThreadSanitizer (target=editor, dev_build=yes, use_tsan=yes, use_llvm=yes, linker=lld)
cache-name: linux-editor-thread-sanitizer
target: editor
scons-flags: >-
dev_build=yes
use_tsan=yes
use_llvm=yes
linker=lld
bin: ./bin/godot.linuxbsd.editor.dev.x86_64.llvm.san
- name: Template w/ Mono, release (target=template_release)
cache-name: linux-template-mono
target: template_release
scons-flags: module_mono_enabled=yes
bin: ./bin/godot.linuxbsd.template_release.x86_64.mono
artifact: true
- name: Template w/ Mono, debug (target=template_debug)
cache-name: linux-template-mono-debug
target: template_debug
scons-flags: module_mono_enabled=yes
bin: ./bin/godot.linuxbsd.template_debug.x86_64.mono
artifact: true
- name: Minimal template (target=template_release, everything disabled)
cache-name: linux-template-minimal
target: template_release
scons-flags: >-
modules_enabled_by_default=no
module_text_server_fb_enabled=no
disable_3d=yes
disable_advanced_gui=yes
disable_physics_2d=yes
disable_physics_3d=yes
deprecated=no
minizip=no
brotli=no
bin: ./bin/godot.linuxbsd.template_release.x86_64
artifact: true
steps:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: recursive
- name: Setup dependencies
run: |
sudo apt-get update
sudo apt-get install libwayland-bin # TODO: Figure out somehow how to embed this one.
if [ "${{ matrix.proj-test }}" == "true" -o "${{ matrix.proj-export }}" == "true" ]; then
sudo apt-get install mesa-vulkan-drivers
fi
- name: Free disk space on runner
run: |
echo "Disk usage before:" && df -h
sudo rm -rf /usr/local/lib/android
echo "Disk usage after:" && df -h
- name: Restore Godot build cache
uses: ./.github/actions/godot-cache-restore
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Setup Python and SCons
if: "!matrix.legacy-scons"
uses: ./.github/actions/godot-deps
- name: Setup Python and SCons (legacy versions)
if: matrix.legacy-scons
uses: ./.github/actions/godot-deps
with:
# Sync with Ensure*Version in SConstruct.
python-version: 3.9
scons-version: 4.0
- name: Force remove preinstalled .NET SDKs
if: matrix.build-mono
run: |
sudo rm -rf /usr/share/dotnet/sdk/*
- name: Setup older .NET SDK as baseline
if: matrix.build-mono
uses: actions/setup-dotnet@v4
with:
# Targeting the oldest version we want to support to ensure it still builds.
dotnet-version: 8.0.100
- name: Download pre-built AccessKit
shell: sh
id: accesskit-sdk
run: |
if python ./misc/scripts/install_accesskit.py; then
echo "ACCESSKIT_ENABLED=yes" >> "$GITHUB_OUTPUT"
else
echo "::warning::AccessKit SDK installation failed, building without AccessKit support."
echo "ACCESSKIT_ENABLED=no" >> "$GITHUB_OUTPUT"
fi
- name: Install mold linker
if: matrix.proj-test
uses: rui314/setup-mold@v1
- name: Compilation
uses: ./.github/actions/godot-build
with:
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} accesskit=${{ steps.accesskit-sdk.outputs.ACCESSKIT_ENABLED }}
platform: linuxbsd
target: ${{ matrix.target }}
- name: Style checks via pre-commit
if: matrix.clang-tidy
uses: pre-commit/action@v3.0.1
with:
extra_args: --files ${{ inputs.changed-files }} --hook-stage manual clang-tidy
- name: Compilation (godot-cpp)
uses: ./.github/actions/godot-cpp-build
if: matrix.godot-cpp
with:
bin: ${{ matrix.bin }}
scons-flags: target=template_debug dev_build=yes verbose=yes
godot-cpp-branch: ${{ env.GODOT_CPP_BRANCH }}
- name: Save Godot build cache
uses: ./.github/actions/godot-cache-save
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Generate C# glue
if: matrix.build-mono
run: |
${{ matrix.bin }} --headless --generate-mono-glue ./modules/mono/glue
- name: Build .NET solutions
if: matrix.build-mono
run: |
dotnet --info
./modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --godot-platform=linuxbsd --werror
- name: Prepare artifact
if: matrix.artifact
run: |
strip bin/godot.*
chmod +x bin/godot.*
- name: Upload artifact
uses: ./.github/actions/upload-artifact
if: matrix.artifact
with:
name: ${{ matrix.cache-name }}
- name: Unit tests
run: |
${{ matrix.bin }} --version
${{ matrix.bin }} --help
${{ matrix.bin }} --headless --test --force-colors
- name: .NET source generators tests
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
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"
${{ matrix.bin }} --doctool --headless 2>&1 > /dev/null || true
git diff --color --exit-code && ! git ls-files --others --exclude-standard | sed -e 's/^/New doc file missing in PR: /' | grep 'xml$'
# Check API backwards compatibility
- name: Check for GDExtension compatibility JSON check
if: matrix.api-compat
run: |
./misc/scripts/validate_extension_api.sh "${{ matrix.bin }}"
- name: Test GDExtension compatibility load methods
uses: ./.github/actions/godot-compat-test
if: matrix.api-compat
with:
bin: ${{ matrix.bin }}
reftags: "4.5-stable,4.4-stable"
# Download and run the test project
- name: Test Godot project
uses: ./.github/actions/godot-project-test
if: matrix.proj-test
with:
bin: ${{ matrix.bin }}
# Test project export
- name: Test project export
uses: ./.github/actions/godot-project-export
if: matrix.proj-export
with:
bin: ${{ matrix.bin }}
# Test the project converter
- name: Test project converter
uses: ./.github/actions/godot-converter-test
if: matrix.proj-conv
with:
bin: ${{ matrix.bin }}

View file

@ -1,110 +0,0 @@
name: 🍎 macOS Builds
on:
workflow_call:
workflow_dispatch:
# Global Settings
env:
SCONS_FLAGS: >-
dev_mode=yes
module_text_server_fb_enabled=yes
jobs:
build-macos:
# From https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job#choosing-github-hosted-runners
runs-on: macos-latest
name: ${{ matrix.name }}
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
include:
- name: Editor (target=editor)
cache-name: macos-editor
target: editor
bin: ./bin/godot.macos.editor.universal
- name: Template (target=template_release)
cache-name: macos-template
target: template_release
scons-flags: debug_symbols=no
bin: ./bin/godot.macos.template_release.universal
steps:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: recursive
# From https://github.com/actions/runner-images/blob/main/images/macos
- name: Select Xcode 26
run: sudo xcode-select -s /Applications/Xcode_26.0.1.app
- name: Restore Godot build cache
uses: ./.github/actions/godot-cache-restore
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Setup Python and SCons
uses: ./.github/actions/godot-deps
- name: Download pre-built AccessKit
shell: sh
id: accesskit-sdk
run: |
if python3 ./misc/scripts/install_accesskit.py; then
echo "ACCESSKIT_ENABLED=yes" >> "$GITHUB_OUTPUT"
else
echo "::warning::AccessKit SDK installation failed, building without AccessKit support."
echo "ACCESSKIT_ENABLED=no" >> "$GITHUB_OUTPUT"
fi
- name: Setup Vulkan SDK
id: vulkan-sdk
run: |
if sh misc/scripts/install_vulkan_sdk_macos.sh; then
echo "VULKAN_ENABLED=yes" >> "$GITHUB_OUTPUT"
else
echo "::warning::macOS: Vulkan SDK installation failed, building without Vulkan support."
echo "VULKAN_ENABLED=no" >> "$GITHUB_OUTPUT"
fi
continue-on-error: true
- name: Compilation (x86_64)
uses: ./.github/actions/godot-build
with:
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} arch=x86_64 vulkan=${{ steps.vulkan-sdk.outputs.VULKAN_ENABLED }} accesskit=${{ steps.accesskit-sdk.outputs.ACCESSKIT_ENABLED }}
platform: macos
target: ${{ matrix.target }}
- name: Compilation (arm64)
uses: ./.github/actions/godot-build
with:
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} arch=arm64 vulkan=${{ steps.vulkan-sdk.outputs.VULKAN_ENABLED }} accesskit=${{ steps.accesskit-sdk.outputs.ACCESSKIT_ENABLED }}
platform: macos
target: ${{ matrix.target }}
- name: Save Godot build cache
uses: ./.github/actions/godot-cache-save
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Prepare artifact
run: |
lipo -create ./bin/godot.macos.${{ matrix.target }}.x86_64 ./bin/godot.macos.${{ matrix.target }}.arm64 -output ./bin/godot.macos.${{ matrix.target }}.universal
rm ./bin/godot.macos.${{ matrix.target }}.x86_64 ./bin/godot.macos.${{ matrix.target }}.arm64
strip bin/godot.*
chmod +x bin/godot.*
- name: Upload artifact
uses: ./.github/actions/upload-artifact
with:
name: ${{ matrix.cache-name }}
- name: Unit tests
run: |
${{ matrix.bin }} --version
${{ matrix.bin }} --help
${{ matrix.bin }} --test --force-colors

View file

@ -1,54 +0,0 @@
name: 🔗 GHA
on: [push, pull_request, merge_group, workflow_dispatch]
concurrency:
group: ${{ github.workflow }}|${{ github.ref_name }}
cancel-in-progress: true
jobs:
# First stage: Only static checks, fast and prevent expensive builds from running.
static-checks:
if: ${{ !vars.DISABLE_GODOT_CI || github.run_attempt > 1 || github.event_name == 'workflow_dispatch' }}
name: 📊 Static checks
uses: ./.github/workflows/static_checks.yml
# Second stage: Run all the builds and some of the tests.
android-build:
name: 🤖 Android
needs: static-checks
if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
uses: ./.github/workflows/android_builds.yml
ios-build:
name: 🍏 iOS
needs: static-checks
if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
uses: ./.github/workflows/ios_builds.yml
linux-build:
name: 🐧 Linux
needs: static-checks
if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
uses: ./.github/workflows/linux_builds.yml
with:
changed-files: ${{ needs.static-checks.outputs.changed-files }}
macos-build:
name: 🍎 macOS
needs: static-checks
if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
uses: ./.github/workflows/macos_builds.yml
windows-build:
name: 🏁 Windows
needs: static-checks
if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
uses: ./.github/workflows/windows_builds.yml
web-build:
name: 🌐 Web
needs: static-checks
if: needs.static-checks.outputs.sources-changed == 'true' || github.event_name != 'pull_request'
uses: ./.github/workflows/web_builds.yml

View file

@ -1,47 +0,0 @@
name: 📊 Static Checks
on:
workflow_call:
outputs:
changed-files:
description: A list of changed files.
value: ${{ jobs.static-checks.outputs.changed-files }}
sources-changed:
description: Determines if any source files were changed.
value: ${{ jobs.static-checks.outputs.sources-changed }}
workflow_dispatch:
jobs:
static-checks:
name: Code style, file formatting, and docs
runs-on: ubuntu-24.04
timeout-minutes: 30
outputs:
changed-files: '"${{ steps.changed-files.outputs.everything_all_changed_files }}"' # Wrap with quotes to bookend internal quote separators.
sources-changed: ${{ steps.changed-files.outputs.sources_any_changed }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0 # Treeless clone. Slightly less performant than a shallow clone, but makes finding diffs instantaneous.
filter: tree:0 # See: https://github.blog/open-source/git/get-up-to-speed-with-partial-clone-and-shallow-clone/
# This needs to happen before Python and npm execution; it must happen before any extra files are written.
- name: .gitignore checks (gitignore_check.sh)
run: |
bash ./misc/scripts/gitignore_check.sh
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v47
with:
safe_output: false # Output passed to environment variable to avoid command injection.
separator: '" "' # To account for paths with spaces, ensure our items are split by quotes internally.
skip_initial_fetch: true
files_yaml_from_source_file: .github/changed_files.yml
- name: Style checks via pre-commit
uses: pre-commit/action@v3.0.1
env:
CHANGED_FILES: '"${{ steps.changed-files.outputs.everything_all_changed_files }}"' # Wrap with quotes to bookend internal quote separators.
with:
extra_args: --files ${{ env.CHANGED_FILES }}

View file

@ -1,77 +0,0 @@
name: 🌐 Web Builds
on:
workflow_call:
workflow_dispatch:
# Global Settings
env:
SCONS_FLAGS: >-
dev_mode=yes
debug_symbols=no
use_closure_compiler=yes
EM_VERSION: 4.0.11
jobs:
web-template:
runs-on: ubuntu-24.04
name: ${{ matrix.name }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- name: Template w/ threads, 64-bit (target=template_release, threads=yes, arch=wasm64)
cache-name: web-template
target: template_release
scons-flags: threads=yes arch=wasm64
artifact: true
- name: Template w/o threads, 32-bit (target=template_release, threads=no, arch=wasm32)
cache-name: web-nothreads-template
target: template_release
scons-flags: threads=no arch=wasm32
artifact: true
steps:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: recursive
- name: Set up Emscripten latest
uses: mymindstorm/setup-emsdk@v14
with:
version: ${{ env.EM_VERSION }}
no-cache: true
- name: Verify Emscripten setup
run: |
emcc -v
- name: Restore Godot build cache
uses: ./.github/actions/godot-cache-restore
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Setup Python and SCons
uses: ./.github/actions/godot-deps
- name: Compilation
uses: ./.github/actions/godot-build
with:
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }}
platform: web
target: ${{ matrix.target }}
- name: Save Godot build cache
uses: ./.github/actions/godot-cache-save
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Upload artifact
uses: ./.github/actions/upload-artifact
if: matrix.artifact
with:
name: ${{ matrix.cache-name }}

View file

@ -1,136 +0,0 @@
name: 🏁 Windows Builds
on:
workflow_call:
workflow_dispatch:
# Global Settings
env:
SCONS_FLAGS: >-
dev_mode=yes
module_text_server_fb_enabled=yes
debug_symbols=no
"angle_libs=${{ github.workspace }}/"
SCONS_CACHE_MSVC_CONFIG: true
PYTHONIOENCODING: utf8
jobs:
build-windows:
# Windows 10 with latest image
runs-on: windows-latest
name: ${{ matrix.name }}
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
include:
- name: Editor (target=editor)
cache-name: windows-editor
target: editor
scons-flags: >-
windows_subsystem=console
vsproj=yes
vsproj_gen_only=no
bin: ./bin/godot.windows.editor.x86_64.exe
compiler: msvc
- name: Editor w/ clang-cl (target=editor, use_llvm=yes)
cache-name: windows-editor-clang
target: editor
scons-flags: >-
windows_subsystem=console
use_llvm=yes
bin: ./bin/godot.windows.editor.x86_64.llvm.exe
compiler: clang
- name: Template (target=template_release)
cache-name: windows-template
target: template_release
bin: ./bin/godot.windows.template_release.x86_64.console.exe
compiler: msvc
- name: Template w/ GCC (target=template_release, use_mingw=yes)
cache-name: windows-template-gcc
# MinGW takes MUCH longer to compile; save time by only targeting Template.
target: template_release
scons-flags: use_mingw=yes
bin: ./bin/godot.windows.template_release.x86_64.console.exe
compiler: gcc
steps:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: recursive
- name: Restore Godot build cache
uses: ./.github/actions/godot-cache-restore
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Setup Python and SCons
uses: ./.github/actions/godot-deps
- name: Download Direct3D 12 SDK components
shell: sh
id: d3d12-sdk
run: |
if python ./misc/scripts/install_d3d12_sdk_windows.py; then
echo "D3D12_ENABLED=yes" >> "$GITHUB_OUTPUT"
else
echo "::warning::Windows: Direct3D 12 SDK installation failed, building without Direct3D 12 support."
echo "D3D12_ENABLED=no" >> "$GITHUB_OUTPUT"
fi
continue-on-error: true
- name: Download pre-built ANGLE static libraries
uses: dsaltares/fetch-gh-release-asset@1.1.2
with:
repo: godotengine/godot-angle-static
version: tags/chromium/6601.2
file: godot-angle-static-x86_64-${{ matrix.compiler == 'gcc' && 'gcc' || 'msvc' }}-release.zip
target: angle/angle.zip
- name: Extract pre-built ANGLE static libraries
run: Expand-Archive -Force angle/angle.zip ${{ github.workspace }}/
- name: Download pre-built AccessKit
shell: sh
id: accesskit-sdk
run: |
if python ./misc/scripts/install_accesskit.py; then
echo "ACCESSKIT_ENABLED=yes" >> "$GITHUB_OUTPUT"
else
echo "::warning::AccessKit SDK installation failed, building without AccessKit support."
echo "ACCESSKIT_ENABLED=no" >> "$GITHUB_OUTPUT"
fi
- name: Compilation
uses: ./.github/actions/godot-build
with:
scons-flags: ${{ env.SCONS_FLAGS }} ${{ matrix.scons-flags }} d3d12=${{ steps.d3d12-sdk.outputs.D3D12_ENABLED }} accesskit=${{ steps.accesskit-sdk.outputs.ACCESSKIT_ENABLED }}
platform: windows
target: ${{ matrix.target }}
- name: Save Godot build cache
uses: ./.github/actions/godot-cache-save
with:
cache-name: ${{ matrix.cache-name }}
continue-on-error: true
- name: Prepare artifact
if: matrix.compiler == 'msvc'
run: |
Remove-Item bin/* -Include *.exp,*.lib,*.pdb -Force
- name: Upload artifact
if: matrix.compiler == 'msvc'
uses: ./.github/actions/upload-artifact
with:
name: ${{ matrix.cache-name }}
- name: Unit tests
run: |
${{ matrix.bin }} --version
${{ matrix.bin }} --help
${{ matrix.bin }} --test --force-colors

11
engine/.gitignore vendored
View file

@ -43,7 +43,6 @@ run_ninja_env.bat
# Generated by Godot binary
.import/
/gdextension_interface.h
/gdextension_interface.json
extension_api.json
logs/
@ -90,7 +89,6 @@ local.properties
*.iml
.gradletasknamecache
project.properties
platform/android/java/build/
platform/android/java/*/.cxx/
platform/android/java/*/build/
platform/android/java/*/libs/
@ -155,10 +153,6 @@ cppcheck-cppcheck-build-dir/
*.geany
.geanyprj
# GNU patch
*.orig
*.rej
# Gprof
gmon.out
@ -222,10 +216,7 @@ xcuserdata/
*.xcscmblueprint
*.xccheckout
*.xcodeproj/*
!misc/misc/dist/apple_embedded_xcode/godot.xcodeproj/project.pbxproj
# Zed
.zed/
!misc/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
##############################
### Visual Studio specific ###

View file

@ -7,7 +7,6 @@ Alexander Holland <alexander.holland@live.de> <AlexHolly>
Alfred Reinold Baudisch <alfred@alfredbaudisch.com>
Andrea Catania <info@andreacatania.com>
Anish Bhobe <anishbhobe@hotmail.com>
Anish Kumar <mishragames@gmail.com>
Anutrix <numaanzaheerahmed@yahoo.com>
Aren Villanueva <arenvillanueva@yomogi-soft.com> <aren@displaysweet.com>
Ariel Manzur <ariel@godotengine.org>
@ -21,13 +20,11 @@ A Thousand Ships <96648715+AThousandShips@users.noreply.github.com>
A Thousand Ships <96648715+AThousandShips@users.noreply.github.com> <over999ships@gmail.com>
Bastiaan Olij <mux213@gmail.com>
Benjamin <mafortion.benjamin@gmail.com>
Bernat Arlandis <berarma@hotmail.com>
Bernhard Liebl <Bernhard.Liebl@gmx.org> <poke1024@gmx.de>
Bernhard Liebl <Bernhard.Liebl@gmx.org> <poke1024@gmx.org>
Bruno Lourenço <madequa@users.noreply.github.com> <bmlourenco@gmail.com>
Chaosus <chaosus89@gmail.com>
ChibiDenDen <pdaniq@gmail.com>
chocola-mint <56677134+chocola-mint@users.noreply.github.com>
Chris Bradfield <chris@kidscancode.org> <cb@scribe.net>
Clay John <claynjohn@gmail.com>
Clay John <claynjohn@gmail.com> <clayjohn@shaw.ca>
@ -37,7 +34,6 @@ dankan1890 <mewuidev2@gmail.com>
Daniel J. Ramirez <djrmuv@gmail.com>
Dario <dariosamo@gmail.com>
David Cambré <david.cambre@gmail.com> <David.Cambre@gmail.com>
Dery Almas <dery@posteo.net> <riteo@posteo.net>
DmitriySalnikov <salnikov.mine@yandex.ru>
DmitriySalnikov <salnikov.mine@yandex.ru> <dimokgamer@gmail.com>
Dominik 'dreamsComeTrue' Jasiński <dominikjasinski@o2.pl>
@ -117,8 +113,6 @@ Liz Haas <27thLiz@gmail.com> <hinsbart@gmail.com>
Liz Haas <27thLiz@gmail.com> <hinsbart@users.noreply.github.com>
Liz Haas <27thLiz@gmail.com> <entenflugstuhl@gmail.com>
Logan Lang <devloglogan@gmail.com>
Luo Zhihao <luo_zhihao@outlook.com>
Luo Zhihao <luo_zhihao@outlook.com> <luo_zhihao_jx@qq.com>
Manuele Finocchiaro <m4nu3lf@gmail.com>
Manuel Strey <manuel.strey@gmx.de>
Marcel Admiraal <madmiraal@users.noreply.github.com>
@ -136,13 +130,11 @@ Max Hilbrunner <m.hilbrunner@gmail.com> <mhilbrunner@users.noreply.github.com>
MewPurPur <mew.pur.pur@abv.bg>
Michael Alexsander <michaelalexsander@protonmail.com>
Micky <micheledevita2@gmail.com> <66727710+Mickeon@users.noreply.github.com>
MrCdK <contact@mrcdk.com>
Nathan Franke <natfra@pm.me> <nathanwfranke@gmail.com>
Nathan Lovato <nathan@gdquest.com>
Nathan Warden <nathan@nathanwarden.com> <nathanwardenlee@icloud.com>
Nazarii <nazarii.yablonskyi.pp.2022@lpnu.ua>
Nicholas Huelin <62965063+SirQuartz@users.noreply.github.com>
nikitalita <69168929+nikitalita@users.noreply.github.com>
Nils ANDRÉ-CHANG <nils@nilsand.re>
Nils ANDRÉ-CHANG <nils@nilsand.re> <nils.andre.chang@gmail.com>
Nông Văn Tình <vannongtinh@gmail.com>
@ -173,17 +165,14 @@ Rémi Verschelde <rverschelde@gmail.com> <remi@verschelde.fr>
Rhody Lugo <rhodylugo@gmail.com> <rhodylugo@me.com>
Ricardo Subtil <ricasubtil@gmail.com>
Rindbee <idleman@yeah.net>
Robert Yevdokimov <robert.yevdokimov@autStand.com>
Robert Yevdokimov <robert.yevdokimov@autStand.com> <105675984+ryevdokimov@users.noreply.github.com>
Riteo Siuga <riteo@posteo.net>
Robin Hübner <profan@prfn.se> <robinhubner@gmail.com>
romulox_x <romulox_x@yahoo.com>
Rudolph Bester <Rudolph.f.Bester@gmail.com> <Rudolph.f.bester@gmail.com>
rune-scape <allie.smith.epic@gmail.com>
rune-scape <allie.smith.epic@gmail.com> <spartacrafter@gmail.com>
Ruslan Mustakov <r.mustakov@gmail.com> <ruslan.mustakov@xored.com>
Ryan <73148864+Ryan-000@users.noreply.github.com>
Saracen <SaracenOne@gmail.com>
Septian Ganendra S. K. <septgsk@gmail.com>
sheepandshepherd <sheepandshepherd@hotmail.com> <sheepandshepherd@users.noreply.github.com>
Silc 'Tokage' Renew <tokage.it.lab@gmail.com>
Silc 'Tokage' Renew <tokage.it.lab@gmail.com> <61938263+TokageItLab@users.noreply.github.com>
@ -193,13 +182,11 @@ tetrapod00 <145553014+tetrapod00@users.noreply.github.com>
Theo Hallenius <redsymbzone@hotmail.com>
Tomasz Chabora <kobewi4e@gmail.com>
Twarit <wtwarit@gmail.com>
vaner-org <angadmishra@outlook.com>
Vitika9 <vitika.program@gmail.com>
V.VamsiKrishna <vk@bsb.in> <vamsikrishna.v@gmail.com>
Wilhem Barbier <nounoursheureux@openmailbox.org> <wilhem.b@free.fr>
Wilhem Barbier <nounoursheureux@openmailbox.org> <schtroumps31@gmail.com>
Will Nations <willnationsdev@gmail.com>
ydeltastar <ydeltastar@gmail.com>
yg2f <yoann@terminajones.com>
Yuri Sizov <yuris@humnom.net> <pycbouh@users.noreply.github.com>
Yuri Sizov <yuris@humnom.net> <yaschik4ilicha@gmail.com>

View file

@ -6,19 +6,12 @@ exclude: |
.*thirdparty/.*|
.*-(dll|dylib|so)_wrap\.[ch]|
platform/android/java/editor/src/main/java/com/android/.*|
platform/android/java/lib/src/main/java/com/google/.*
platform/android/java/lib/src/com/google/.*
)$
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable
exclude: (SConstruct|SCsub)$ # SCons files use shebangs for syntax highlighting only.
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v21.1.7
rev: v20.1.0
hooks:
- id: clang-format
files: \.(c|h|cpp|hpp|cc|hh|cxx|hxx|m|mm|inc|java)$
@ -29,36 +22,30 @@ repos:
types_or: [text]
args: [-style=file:misc/utility/clang_format_glsl.yml]
# Not automatically triggered (because it requires compile_commands.json to be up-to-date).
# Invoke it manually via `pre-commit run --hook-stage manual clang-tidy`
- repo: https://github.com/pocc/pre-commit-hooks
rev: v1.3.5
hooks:
- id: clang-tidy
# TODO .inc ignored for now because they don't include their parent header.
# TODO Platform-specific subfolders currently fail, we should try to include them
files: ^(core|main|scene)/.*\.(c|h|cpp|hpp|cc|hh|cxx|hxx|m|mm|java)$
# No unknown warning suppression used for easier compatibility with gcc
args: [--fix, --quiet, --use-color, -p=compile_commands.json, -extra-arg=-Wno-unknown-warning-option]
files: \.(c|h|cpp|hpp|cc|hh|cxx|hxx|m|mm|inc|java|glsl)$
args: [--fix, --quiet, --use-color]
types_or: [text]
additional_dependencies: [clang-tidy==21.1.6]
require_serial: false
stages: [manual]
additional_dependencies: [clang-tidy==20.1.0]
require_serial: true
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.15.0
rev: v0.11.4
hooks:
- id: ruff-check
args: [--color=always]
- id: ruff
args: [--fix]
files: (\.py|SConstruct|SCsub)$
types_or: [text]
- id: ruff-format
args: [--color=always]
files: (\.py|SConstruct|SCsub)$
types_or: [text]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.19.1
rev: v1.14.1 # Latest version that supports Python 3.8
hooks:
- id: mypy
files: \.py$
@ -70,12 +57,15 @@ repos:
- id: codespell
additional_dependencies: [tomli]
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.34.1
hooks:
- id: check-jsonschema
files: ^core/extension/gdextension_interface\.json$
args: ["--schemafile", "core/extension/gdextension_interface.schema.json"]
### Requires Docker; look into alternative implementation.
# - repo: https://github.com/comkieffer/pre-commit-xmllint.git
# rev: 1.0.0
# hooks:
# - id: xmllint
# language: docker
# types_or: [text]
# files: ^(doc/classes|.*/doc_classes)/.*\.xml$
# args: [--schema, doc/class.xsd]
- repo: local
hooks:
@ -102,19 +92,6 @@ repos:
pass_filenames: false
files: ^(gles3|glsl)_builders\.py$
- id: validate-xml
name: validate-xml
language: python
entry: python misc/scripts/validate_xml.py
files: ^(doc/classes|.*/doc_classes)/.*\.xml$
additional_dependencies: [xmlschema]
- id: validate-codeowners
name: validate codeowners
language: python
entry: python misc/scripts/validate_codeowners.py
args: [--unowned]
- id: eslint
name: eslint
language: node
@ -171,9 +148,9 @@ repos:
(?x)^(
core/math/bvh_.*\.inc|
platform/(?!android|ios|linuxbsd|macos|web|windows)\w+/.*|
platform/android/java/lib/src/main/java/org/godotengine/godot/gl/GLSurfaceView\.java|
platform/android/java/lib/src/main/java/org/godotengine/godot/gl/EGLLogWrapper\.java|
platform/android/java/lib/src/main/java/org/godotengine/godot/utils/ProcessPhoenix\.java
platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView\.java|
platform/android/java/lib/src/org/godotengine/godot/gl/EGLLogWrapper\.java|
platform/android/java/lib/src/org/godotengine/godot/utils/ProcessPhoenix\.java
)$
- id: header-guards

View file

@ -34,17 +34,15 @@ name is available.
Aaron Franke (aaronfranke)
Aaron Pagano (aaronp64)
Aaron Record (LightningAA)
Adam Johnston (a-johnston)
Adam Scott (adamscott)
Æio Much (AeioMuch)
Alex Drozd (brno32)
Alexander Hartmann (Alex2782)
Alexander Holland (AlexHolly)
Alex Drozd (brno32)
Alexey Khoroshavin (allkhor)
Allen Pestaluky (allenwp)
Alfred Reinold Baudisch (alfredbaudisch)
Alistair Leslie-Hughes (alesliehughes)
Alket Rexhepi (alketii)
Allen Pestaluky (allenwp)
Alvin Wong (alvinhochun)
Andrea Catania (AndreaCatania)
Andreia Gaita (shana)
@ -55,7 +53,7 @@ name is available.
Angad Kambli (angad-k)
Anilforextra (AnilBK)
Anish Bhobe (KidRigger)
Anish Kumar (syntaxerror247)
Anish Mishra (syntaxerror247)
Anni Ryynänen (anniryynanen)
Anton Yabchinskiy (a12n)
Anutrix
@ -70,7 +68,6 @@ name is available.
Bastiaan Olij (BastiaanOlij)
Ben Brookshire (sheepandshepherd)
Benjamin Larsson (Nallebeorn)
Bernat Arlandis (berarma)
Bernhard Liebl (poke1024)
Bhuvan Vemula (Bhu1-V)
bitsawer
@ -78,7 +75,6 @@ name is available.
BlueCube3310
Bojidar Marinov (bojidar-bg)
Brian Semrau (briansemrau)
BrotherShort
Bruno Lourenço (MadEqua)
Cameron Reikes (creikey)
Camille Mohr-Daurat (pouleyKetchoupp)
@ -86,7 +82,6 @@ name is available.
Carl Olsson (not-surt)
Carter Anderson (cart)
ChibiDenDen
ChocolaMint (chocola-mint)
Chris Bradfield (cbscribe)
Chris Cranford (Naros)
Christian Kaiser (ckaiser)
@ -103,9 +98,7 @@ name is available.
David Cambré (Gallilus)
David Sichma (DavidSichma)
David Snopek (dsnopek)
demolke
derammo
Dery Almas (deralmas)
Dharkael (lupoDharkael)
Dirk Steinmetz (rsjtdrjgfuzkfg)
Dmitry Koteroff (Krakean)
@ -138,7 +131,6 @@ name is available.
Fredia Huya-Kouadio (m4gr3d)
Geequlim
George Marques (vnen)
Gergely Kis (kisg)
Gerrit Großkopf (Grosskopf)
Giganzo
Gilles Roudiere (groud)
@ -168,10 +160,8 @@ name is available.
Jakub Grzesik (kubecz3k)
Jakub Marcowski (Chubercik)
James Buck (jbuck3)
Jamie Pate (jamie-pate)
Jan Haller (Bromeon)
Jason Knight (jasonwinterpixel)
Jayden Sipe (jaydensipe)
Jean-Michel Bernard (jmb462)
Jérôme Gully (Nutriz)
Jia Jun Chai (SkyLucilfer)
@ -182,7 +172,6 @@ name is available.
Johannes Witt (HaSa1002)
Jonathan Nicholl (jtnicholl)
Jordan Schidlowsky (winterpixelgames)
Jorrit Rouwe (jrouwe)
Josh Jones (DarkKilauea)
Joshua Grams (JoshuaGrams)
Juan Linietsky (reduz)
@ -190,30 +179,21 @@ name is available.
Julien Nguyen (Blackiris)
Jummit
Justo Delgado (mrcdk)
K. S. Ernest (iFire) Lee (fire)
Kaleb Reid (Kaleb-Reid)
karroffel
Kasper Arnklit Frandsen (Arnklit)
Kassandra Pucher (PucklaJ)
Kelly Thomas (KellyThomas)
Kit Bishop (kitbdev)
kleonc
KOGA Mitsuhiro (shiena)
Koliur Rahman (dugramen)
Kongfa Waroros (gongpha)
Kostadin Damyanov (Max-Might)
Koyper
K. S. Ernest (iFire) Lee (fire)
Kyle Eichlin (likeich)
Lander (lander-vr)
Lars Pettersson (larspet)
lawnjelly
Leon Krause (leonkrause)
Liz Haas (27thLiz)
Logan Detrick (lodetrick)
Logan Lang (devloglogan)
Lucien Menassol (Kanabenki)
Lukas Tenbrink (Ivorforce)
Luo Zhihao (beicause)
Lyuma
Maganty Rushyendra (mrushyendra)
Magian (magian1127)
@ -221,9 +201,9 @@ name is available.
Malcolm Anderson (Meorge)
Malcolm Nixon (Malcolmnixon)
Manuele Finocchiaro (m4nu3lf)
Marc Gilleron (Zylann)
Marcel Admiraal (madmiraal)
Marcelo Fernandez (marcelofg55)
Marc Gilleron (Zylann)
Marcin Zawiejski (dragmz)
Marcus Brummer (mbrlabs)
Marcus Elg (MCrafterzz)
@ -242,29 +222,25 @@ name is available.
Masoud BH (masoudbh3)
Mateo Kuruk Miccino (kuruk-mm)
Matias N. Goldberg (darksylinc)
MatheusMDX (matheusmdx)
Matthew (skyace65)
Matthew Murphy (mashumafi)
Matthew (skyace65)
Matthias Hölzl (hoelzl)
Max Hilbrunner (mhilbrunner)
Meru Patel (Janglee123)
merumelu
Meru Patel (Janglee123)
MewPurPur
Michael Alexsander (YeldhamDev)
Michael Precup (precup)
Michael Russkikh (Summersay415)
Michał Iwańczuk (iwek7)
MichiRecRoom (LikeLakers2)
Micky (Mickeon)
Mika Viskari (miv391)
Mikael Hermansson (mihe)
Mika Viskari (miv391)
MinusKube
MJacred
Mounir Tohami (WhalesState)
mrezai
Muhammad Huri (CakHuri)
muiroc
Muller-Castro
myaaaaaaaaa
Nathalie Galla (MurderVeggie)
Nathan Franke (nathanfranke)
@ -274,7 +250,6 @@ name is available.
Nicholas Huelin (SirQuartz)
Nikita Lita (nikitalita)
Nils André-Chang (NilsIrl)
Nintorch
Noah Beard (TwistedTwigleg)
Nông Văn Tình (nongvantinh)
Nuno Donato (nunodonato)
@ -284,9 +259,9 @@ name is available.
Pablo Andres Fuente (pafuent)
Pascal Richter (ShyRed)
passivestar
Patrick (firefly2442)
Patrick Dawson (pkdawson)
Patrick Exner (FlameLizard)
Patrick (firefly2442)
patwork
Paul Batty (Paulb23)
Paul Joannon (paulloz)
@ -314,8 +289,9 @@ name is available.
Rhody Lugo (rraallvv)
Ricardo Buring (rburing)
Ricardo Subtil (Ev1lbl0w)
Robert Yevdokimov (ryevdokimov)
Riteo Siuga (Riteo)
Roberto F. Arroyo (robfram)
Robert Yevdokimov (ryevdokimov)
Robin Hübner (profan)
romulox-x
Rudolph Bester (Rudolph-B)
@ -324,15 +300,13 @@ name is available.
Ryan Roden-Corrent (rrcore)
Saniko (sanikoyes)
santouits
Saracen (SaracenOne)
SaracenOne
Septian Ganendra S. K. (sepTN)
Sergey Minakov (naithar)
sersoong
Shiqing (kawa-yoiko)
Silc 'Tokage' Renew (TokageItLab)
Simon Schoenenberger (detomon)
Simon Wenner (swenner)
Skyth (Asilkan) (blueskythlikesclouds)
smix8
snailrhymer
Sofox (TheSofox)
@ -349,27 +323,25 @@ name is available.
thebestnom
Theo Hallenius (TheoXD)
Thomas ten Cate (ttencate)
Timo (toger5)
Timo Schwarzer (timoschwarzer)
Timothé Bonhoure (ajreckof)
Timo (toger5)
Tomasz Chabora (KoBeWi)
Travis Lange (TCROC)
trollodel
Twarit Waikar (IronicallySerious)
Umang Kalra (theoway)
V. Vamsi Krishna (vkbsb)
vaner (vaner-org)
Victor Hampel (havi05)
Vinzenz Feenstra (vinzenz)
Vitika Soni (Vitika9)
박한얼 (volzhs)
V. Vamsi Krishna (vkbsb)
Wilhem Barbier (nounoursheureux)
Will Nations (willnationsdev)
William Deurwaarder (williamd67)
Will Nations (willnationsdev)
Wilson E. Alvarez (Rubonnek)
Xavier Cho (mysticfall)
Xu Huisheng (xuhuisheng)
Yaohua Xiong (xiongyaohua)
ydeltastar
Yevhen Babiichuk (dustdfg)
yg2f (SuperUserNameMan)
Yordan Dolchinkov (Jordyfel)
@ -382,8 +354,6 @@ name is available.
Zi Ye (MajorMcDoom)
ZuBsPaCe
Дмитрий Сальников (DmitriySalnikov)
박한얼 (volzhs)
忘忧の (Daylily-Zeleen)
神麤詭末 (scgm0)
谢天 (jsjtxietian)
风青山 (Rindbee)

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@
This document summarizes the most important points for people interested in
contributing to Godot, especially via bug reports or pull requests.
Godot has a dedicated [Contributing documentation](https://contributing.godotengine.org/en/latest/organization/how_to_contribute.html)
The Godot documentation has a dedicated [Contributing section](https://docs.godotengine.org/en/latest/contributing/how_to_contribute.html)
which details these points and more, and is a recommended read.
## Table of contents
@ -55,17 +55,17 @@ Similar rules can be applied when contributing bug fixes - it's always best to
discuss the implementation in the bug report first if you are not 100% about
what would be the best fix.
You can refer to the [Pull request review process](https://contributing.godotengine.org/en/latest/organization/pull_requests/review_guidelines.html)
You can refer to the [Pull request review process](https://docs.godotengine.org/en/latest/contributing/workflow/pr_review_guidelines.html)
for insights into the intended lifecycle of pull requests. This should help you
ensure that your pull request fulfills the requirements.
In addition to the following tips, also take a look at the
[Engine development guide](https://docs.godotengine.org/en/latest/engine_details/development/index.html)
[Engine development guide](https://docs.godotengine.org/en/latest/contributing/development/index.html)
for an introduction to developing on Godot.
The [Contributing docs](https://contributing.godotengine.org/en/latest/organization/how_to_contribute.html)
also have important information on the [PR workflow](https://contributing.godotengine.org/en/latest/organization/pull_requests/creating_pull_requests.html)
(with a helpful guide for Git usage), and our [Code style guidelines](https://contributing.godotengine.org/en/latest/engine/guidelines/cpp_usage_guidelines.html)
The [Contributing docs](https://docs.godotengine.org/en/latest/contributing/how_to_contribute.html)
also have important information on the [PR workflow](https://docs.godotengine.org/en/latest/contributing/workflow/pr_workflow.html)
(with a helpful guide for Git usage), and our [Code style guidelines](https://docs.godotengine.org/en/latest/contributing/development/code_style_guidelines.html)
which all contributions need to follow.
### Be mindful of your commits
@ -84,7 +84,7 @@ stable state, i.e. if your first commit has a bug that you fixed in the second
commit, try to merge them together before making your pull request. This
includes fixing build issues or typos, adding documentation, etc.
See our [PR workflow](https://contributing.godotengine.org/en/latest/organization/pull_requests/creating_pull_requests.html)
See our [PR workflow](https://docs.godotengine.org/en/latest/contributing/workflow/pr_workflow.html)
documentation for tips on using Git, amending commits and rebasing branches.
This [Git style guide](https://github.com/agis-/git-style-guide) also has some
@ -145,10 +145,10 @@ scripting APIs, you **must** update the class reference to document those.
This is to ensure the documentation coverage doesn't decrease as contributions
are merged.
[Update documentation XML files](https://contributing.godotengine.org/en/latest/documentation/class_reference.html)
[Update documentation XML files](https://docs.godotengine.org/en/latest/contributing/documentation/updating_the_class_reference.html)
using your compiled binary, then fill in the descriptions.
Follow the style guide described in the
[Documentation writing guidelines](https://contributing.godotengine.org/en/latest/documentation/guidelines/docs_writing_guidelines.html).
[Documentation writing guidelines](https://docs.godotengine.org/en/latest/contributing/documentation/docs_writing_guidelines.html).
If your pull request modifies parts of the code in a non-obvious way, make sure
to add comments in the code as well. This helps other people understand the
@ -174,7 +174,7 @@ applicable.
Feel free to contribute standalone pull requests to add new tests or improve
existing tests as well.
See [Unit testing](https://contributing.godotengine.org/en/latest/engine/unit_tests.html)
See [Unit testing](https://docs.godotengine.org/en/latest/contributing/development/core_and_modules/unit_testing.html)
for information on writing tests in Godot's C++ codebase.
## Contributing to Godot translations
@ -182,7 +182,7 @@ for information on writing tests in Godot's C++ codebase.
You can contribute to Godot translations on [Hosted Weblate](https://hosted.weblate.org/projects/godot-engine/),
an open source and web-based translation platform.
Please refer to our [editor and documentation localization guidelines](https://contributing.godotengine.org/en/latest/documentation/translation/index.html)
Please refer to our [editor and documentation localization guidelines](https://docs.godotengine.org/en/latest/contributing/documentation/editor_and_docs_localization.html)
for an overview of the translation resources and what they correspond to.
## Communicating with developers

View file

@ -61,15 +61,11 @@ Copyright: 2011, Ole Kniemeyer, MAXON, www.maxon.net
2007-2014, Juan Linietsky, Ariel Manzur
License: Expat and Zlib
Files: misc/dist/linux/org.godotengine.Godot.appdata.xml
Comment: Linux AppStream Metadata File
Copyright: 2017-2022, Rémi Verschelde
License: CC0-1.0
Files: modules/betsy/alpha_stitch.glsl
modules/betsy/bc1.glsl
modules/betsy/bc4.glsl
modules/betsy/bc6h.glsl
modules/betsy/CrossPlatformSettings_piece_all.glsl
Comment: Betsy
Copyright: 2020-2022, Matias N. Goldberg
License: Expat
@ -83,8 +79,8 @@ 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.h
modules/godot_physics_3d/joints/godot_jacobian_entry_3d.h
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
@ -127,15 +123,17 @@ Copyright: 2020, Manuel Prandini
License: Expat
Files: platform/android/java/editor/src/main/java/com/android/*
platform/android/java/lib/src/main/aidl/com/android/*
platform/android/java/lib/src/main/res/layout/status_bar_ongoing_event_progress_bar.xml
platform/android/java/lib/src/main/java/com/google/android/*
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
platform/android/java/lib/src/org/godotengine/godot/input/InputManagerV16.java
Comment: The Android Open Source Project
Copyright: 2008-2016, The Android Open Source Project
2002, Google, Inc.
License: Apache-2.0
Files: platform/android/java/lib/src/main/java/org/godotengine/godot/utils/ProcessPhoenix.java
Files: platform/android/java/lib/src/org/godotengine/godot/utils/ProcessPhoenix.java
Comment: ProcessPhoenix
Copyright: 2015, Jake Wharton
License: Apache-2.0
@ -147,27 +145,15 @@ Copyright: 2001, Robert Penner
2007-2014, Juan Linietsky, Ariel Manzur
License: Expat
Files: servers/audio/effects/audio_effect_pitch_shift.cpp
Copyright: 2014-present Godot Engine contributors
2007-2014 Juan Linietsky, Ariel Manzur
1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com>
License: Expat and WOL
Files: servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
Comment: NVidia's FXAA 3.11, simplified by Simon Rodriguez
Copyright: 2014-2015, NVIDIA CORPORATION
2017 Simon Rodriguez
License: BSD-3-clause and Expat
Files: servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl
servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
servers/rendering/renderer_rd/shaders/effects/ssao.glsl
servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
servers/rendering/renderer_rd/shaders/effects/ssil.glsl
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
servers/rendering/renderer_rd/shaders/ssao_interleave.glsl
servers/rendering/renderer_rd/shaders/ssao.glsl
servers/rendering/renderer_rd/shaders/ssil_blur.glsl
servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl
servers/rendering/renderer_rd/shaders/ssil_interleave.glsl
servers/rendering/renderer_rd/shaders/ssil.glsl
Comment: Intel ASSAO and related files
Copyright: 2016, Intel Corporation
License: Expat
@ -177,18 +163,6 @@ Comment: Temporal Anti-Aliasing resolve implementation
Copyright: 2016, Panos Karabelas
License: Expat
Files: servers/rendering/renderer_rd/shaders/effects/smaa_blending.glsl
servers/rendering/renderer_rd/shaders/effects/smaa_weight_calculation.glsl
servers/rendering/renderer_rd/shaders/effects/smaa_edge_detection.glsl
thirdparty/smaa/*
Comment: Subpixel Morphological Antialiasing
Copyright: 2013, Jorge Jimenez
2013, Jose I. Echevarria
2013, Belen Masia
2013, Fernando Navarro
2013, Diego Gutierrez
License: Expat
Files: thirdparty/accesskit/*
Comment: AccessKit
Copyright: 2023, The AccessKit Authors.
@ -211,12 +185,12 @@ License: BSD-3-clause
Files: thirdparty/astcenc/*
Comment: Arm ASTC Encoder
Copyright: 2011-2025, Arm Limited
Copyright: 2011-2024, Arm Limited
License: Apache-2.0
Files: thirdparty/basis_universal/*
Comment: Basis Universal
Copyright: 2019-2025, Binomial LLC.
Copyright: 2019-2024, Binomial LLC.
License: Apache-2.0
Files: thirdparty/brotli/*
@ -224,7 +198,7 @@ Comment: Brotli
Copyright: 2009, 2010, 2013-2016 by the Brotli Authors.
License: Expat
Files: thirdparty/certs/ca-bundle.crt
Files: thirdparty/certs/ca-certificates.crt
Comment: CA certificates
Copyright: Mozilla Contributors
License: MPL-2.0
@ -255,11 +229,6 @@ Comment: doctest
Copyright: 2016-2023, Viktor Kirilov
License: Expat
Files: thirdparty/dr_libs/*
Comment: dr_libs
Copyright: 2020, David Reid
License: Unlicense or MIT-0
Files: thirdparty/embree/*
Comment: Embree
Copyright: 2009-2021 Intel Corporation
@ -280,11 +249,6 @@ Comment: DroidSans font
Copyright: 2008, The Android Open Source Project
License: Apache-2.0
Files: thirdparty/fonts/Inter*.woff2
Comment: Inter font
Copyright: 2016, The Inter Project Authors
License: OFL-1.1
Files: thirdparty/fonts/JetBrainsMono_Regular.woff2
Comment: JetBrains Mono font
Copyright: 2020, JetBrains s.r.o.
@ -295,11 +259,6 @@ Comment: Noto Sans font
Copyright: 2012, Google Inc.
License: OFL-1.1
Files: thirdparty/fonts/OpenSans*.woff2
Comment: Open Sans font
Copyright: 2020, The Open Sans Project Authors
License: OFL-1.1
Files: thirdparty/fonts/Vazirmatn*.woff2
Comment: Vazirmatn font
Copyright: 2015, The Vazirmatn Project Authors.
@ -307,14 +266,9 @@ License: OFL-1.1
Files: thirdparty/freetype/*
Comment: The FreeType Project
Copyright: 1996-2025, David Turner, Robert Wilhelm, and Werner Lemberg.
Copyright: 1996-2023, David Turner, Robert Wilhelm, and Werner Lemberg.
License: FTL
Files: thirdparty/gamepadmotionhelpers/*
Comment: GamepadMotionHelpers
Copyright: 2020-2023, Julian "Jibb" Smart
License: Expat
Files: thirdparty/glad/*
Comment: glad
Copyright: 2013-2022, David Herberth
@ -333,12 +287,6 @@ Comment: Graphite engine
Copyright: 2010, SIL International
License: Expat
Files: thirdparty/grisu2/*
Comment: Grisu2 float serialization algorithm
Copyright: 2009, Florian Loitsch
2018-2023, The simdjson authors
License: Expat and Apache-2.0
Files: thirdparty/harfbuzz/*
Comment: HarfBuzz text shaping library
Copyright: 2010-2022, Google, Inc.
@ -370,18 +318,16 @@ Comment: Jolt Physics
Copyright: 2021, Jorrit Rouwe
License: Expat
Files: thirdparty/jpeg-compressor/*
Comment: jpeg-compressor
Copyright: 2012, Rich Geldreich
License: public-domain or Apache-2.0
Files: thirdparty/libbacktrace/*
Comment: libbacktrace
Copyright: 2012-2021, Free Software Foundation, Inc.
License: BSD-3-clause
Files: thirdparty/libjpeg-turbo/*
Comment: libjpeg-turbo
Copyright: 2009-2025, D. R. Commander
2015, Viktor Szathmáry.
1991-2020, Thomas G. Lane, Guido Vollbeding
License: BSD-3-clause and IJG
Files: thirdparty/libktx/*
Comment: KTX
Copyright: 2013-2020, Mark Callow
@ -395,8 +341,8 @@ License: BSD-3-clause
Files: thirdparty/libpng/*
Comment: libpng
Copyright: 1995-2026, The PNG Reference Library Authors.
2018-2026, Cosmin Truta.
Copyright: 1995-2025, The PNG Reference Library Authors.
2018-2025, Cosmin Truta.
2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
1996-1997, Andreas Dilger.
1995-1996, Guy Eric Schalnat, Group 42, Inc.
@ -419,7 +365,7 @@ License: BSD-3-clause
Files: thirdparty/manifold/*
Comment: Manifold
Copyright: 2020-2025, The Manifold Authors
Copyright: 2020-2024, The Manifold Authors
License: Apache-2.0
Files: thirdparty/mbedtls/*
@ -432,19 +378,19 @@ Comment: meshoptimizer
Copyright: 2016-2024, Arseny Kapoulkine
License: Expat
Files: thirdparty/metal-cpp/*
Comment: metal-cpp
Copyright: 2024, Apple Inc.
License: Apache-2.0
Files: thirdparty/mingw-std-threads/*
Comment: mingw-std-threads
Copyright: 2016, Mega Limited
License: BSD-2-clause
Files: thirdparty/minimp3/*
Comment: MiniMP3
Copyright: lieff
License: CC0-1.0
Files: thirdparty/miniupnpc/*
Comment: MiniUPnP Project
Copyright: 2005-2025, Thomas Bernard
Copyright: 2005-2024, Thomas Bernard
License: BSD-3-clause
Files: thirdparty/minizip/*
@ -519,7 +465,7 @@ Files: thirdparty/misc/r128.c
thirdparty/misc/r128.h
Comment: r128 library
Copyright: Alan Hickman
License: Unlicense
License: public-domain or Unlicense
Files: thirdparty/misc/smaz.c
thirdparty/misc/smaz.h
@ -531,12 +477,12 @@ Files: thirdparty/misc/smolv.cpp
thirdparty/misc/smolv.h
Comment: SMOL-V
Copyright: 2016-2024, Aras Pranckevicius
License: Unlicense or Expat
License: public-domain or Unlicense or Expat
Files: thirdparty/misc/stb_rect_pack.h
Comment: stb libraries
Copyright: Sean Barrett
License: Unlicense or Expat
License: public-domain or Unlicense or Expat
Files: thirdparty/misc/yuv2rgb.h
Comment: YUV2RGB
@ -545,12 +491,12 @@ License: BSD-2-clause
Files: thirdparty/msdfgen/*
Comment: Multi-channel signed distance field generator
Copyright: 2014-2025, Viktor Chlumsky
Copyright: 2014-2024, Viktor Chlumsky
License: Expat
Files: thirdparty/openxr/*
Comment: OpenXR Loader
Copyright: 2020-2025, The Khronos Group Inc.
Copyright: 2020-2023, The Khronos Group Inc.
License: Apache-2.0
Files: thirdparty/pcre2/*
@ -569,36 +515,16 @@ Comment: RVO2
Copyright: 2016, University of North Carolina at Chapel Hill
License: Apache-2.0
Files: thirdparty/sdl/*
Comment: SDL
Copyright: 1997-2025, Sam Lantinga
License: Zlib
Files: thirdparty/sdl/hidapi/*
Comment: hidapi
Copyright: 2010, Alan Ott, Signal 11 Software
License: BSD-3-clause
Files: thirdparty/spirv-cross/*
Comment: SPIRV-Cross
Copyright: 2015-2021, Arm Limited
License: Apache-2.0 or Expat
Files: thirdparty/spirv-headers/*
Comment: SPIRV-Headers
Copyright: 2015-2024, The Khronos Group Inc.
License: Expat
Files: thirdparty/spirv-reflect/*
Comment: SPIRV-Reflect
Copyright: 2017-2022, Google Inc.
License: Apache-2.0
Files: thirdparty/swappy-frame-pacing/*
Comment: Swappy
Copyright: 2019, The Android Open Source Project
License: Apache-2.0
Files: thirdparty/thorvg/*
Comment: ThorVG
Copyright: 2020-2024, The ThorVG Project
@ -623,19 +549,19 @@ License: BSD-3-clause
Files: thirdparty/volk/*
Comment: volk
Copyright: 2018-2025, Arseny Kapoulkine
Copyright: 2018-2024, Arseny Kapoulkine
License: Expat
Files: thirdparty/vulkan/*
Comment: Vulkan Headers
Copyright: 2015-2025, The Khronos Group Inc.
2015-2025, Valve Corporation
2015-2025, LunarG, Inc.
Copyright: 2014-2024, The Khronos Group Inc.
2014-2024, Valve Corporation
2014-2024, LunarG, Inc.
License: Apache-2.0
Files: thirdparty/vulkan/vk_mem_alloc.h
Comment: Vulkan Memory Allocator
Copyright: 2017-2025, Advanced Micro Devices, Inc.
Copyright: 2017-2024, Advanced Micro Devices, Inc.
License: Expat
Files: thirdparty/wayland/*
@ -647,7 +573,7 @@ Copyright: 2008-2012, Kristian Høgsberg
License: Expat
Files: thirdparty/wayland-protocols/*
Comment: Wayland protocols
Comment: Wayland protocols that add functionality not available in the core protocol
Copyright: 2008-2013, Kristian Høgsberg
2010-2013, Intel Corporation
2013, Rafael Antognolli
@ -658,12 +584,6 @@ Copyright: 2008-2013, Kristian Høgsberg
2015, Red Hat Inc.
License: Expat
Files: thirdparty/wayland-protocols/mesa/wayland-drm.xml
Comment: Mesa Wayland protocols
Copyright: 2008-2011, Kristian Høgsberg
2010-2011, Intel Corporation
License: X11
Files: thirdparty/wslay/*
Comment: Wslay
Copyright: 2011, 2012, 2015, Tatsuhiro Tsujikawa
@ -678,7 +598,7 @@ License: Expat
Files: thirdparty/zlib/*
Comment: zlib
Copyright: 1995-2025, Jean-loup Gailly and Mark Adler
Copyright: 1995-2024, Jean-loup Gailly and Mark Adler
License: Zlib
Files: thirdparty/zstd/*
@ -1558,9 +1478,9 @@ License: FTL
The FreeType Project LICENSE
----------------------------
.
2006-Jan-27
2000-Feb-08
.
Copyright 1996-2002, 2006 by
Copyright 1996-2000 by
David Turner, Robert Wilhelm, and Werner Lemberg
.
.
@ -1600,19 +1520,6 @@ License: FTL
assume no liability related to The FreeType Project.
.
.
Finally, many people asked us for a preferred form for a
credit/disclaimer to use in compliance with this license. We thus
encourage you to use the following text:
.
"""
Portions of this software are copyright © <year> The FreeType
Project (https://freetype.org). All rights reserved.
"""
.
Please replace <year> with the value from the FreeType version you
actually use.
.
.
Legal Terms
===========
.
@ -1664,11 +1571,11 @@ License: FTL
herein, subject to the following conditions:
.
o Redistribution of source code must retain this license file
(`FTL.TXT') unaltered; any additions, deletions or changes to
the original files must be clearly indicated in accompanying
documentation. The copyright notices of the unaltered,
original files must be preserved in all copies of source
files.
(`LICENSE.TXT') unaltered; any additions, deletions or changes
to the original files must be clearly indicated in
accompanying documentation. The copyright notices of the
unaltered, original files must be preserved in all copies of
source files.
.
o Redistribution in binary form must provide a disclaimer that
states that the software is based in part of the work of the
@ -1706,21 +1613,29 @@ License: FTL
.
There are two mailing lists related to FreeType:
.
o freetype@nongnu.org
o freetype@freetype.org
.
Discusses general use and applications of FreeType, as well as
future and wanted additions to the library and distribution.
If you are looking for support, start in this list if you
haven't found anything to help you in the documentation.
.
o freetype-devel@nongnu.org
o devel@freetype.org
.
Discusses bugs, as well as engine internals, design issues,
specific licenses, porting, etc.
.
Our home page can be found at
o http://www.freetype.org
.
https://freetype.org
Holds the current FreeType web page, which will allow you to
download our latest development version and read online
documentation.
.
You can also contact us individually at:
.
David Turner <david.turner@freetype.org>
Robert Wilhelm <robert.wilhelm@freetype.org>
Werner Lemberg <werner.lemberg@freetype.org>
License: HarfBuzz
HarfBuzz is licensed under the so-called "Old MIT" license. Details follow.
@ -1762,42 +1677,6 @@ License: HarfBuzz
ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
License: IJG
The authors make NO WARRANTY or representation, either express or implied,
with respect to this software, its quality, accuracy, merchantability, or
fitness for a particular purpose. This software is provided "AS IS", and you,
its user, assume the entire risk as to its quality and accuracy.
.
This software is copyright (C) 1991-2020, Thomas G. Lane, Guido Vollbeding.
All Rights Reserved except as specified below.
.
Permission is hereby granted to use, copy, modify, and distribute this
software (or portions thereof) for any purpose, without fee, subject to these
conditions:
(1) If any part of the source code for this software is distributed, then this
README file must be included, with this copyright and no-warranty notice
unaltered; and any additions, deletions, or changes to the original files
must be clearly indicated in accompanying documentation.
(2) If only executable code is distributed, then the accompanying
documentation must state that "this software is based in part on the work of
the Independent JPEG Group".
(3) Permission for use of this software is granted only if the user accepts
full responsibility for any undesirable consequences; the authors accept
NO LIABILITY for damages of any kind.
.
These conditions apply to any software derived from or based on the IJG code,
not just to the unmodified library. If you use our work, you ought to
acknowledge us.
.
Permission is NOT granted for the use of any IJG author's name or company name
in advertising or publicity relating to this software or products derived from
it. This software may be referred to only as "the Independent JPEG Group's
software".
.
We specifically permit and encourage the use of this software as the basis of
commercial products, provided that all warranty or liability claims are
assumed by the product vendor.
License: MPL-2.0
Mozilla Public License Version 2.0
==================================
@ -2173,22 +2052,6 @@ License: MPL-2.0
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.
License: MIT-0
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.
.
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.
License: OFL-1.1
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
@ -2333,37 +2196,6 @@ License: Unlicense
.
For more information, please refer to <https://unlicense.org/>
License: WOL
The Wide Open License (WOL)
.
Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice and this license appear in all source copies.
THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF
ANY KIND. See https://dspguru.com/wide-open-license/ for more information.
License: X11
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that\n the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.
.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
License: Zlib
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

View file

@ -5,24 +5,24 @@ contributors, as well as occasional paid contributors thanks to the financial
support of generous donors.
The ways to donate to the project, as well as details on how the funds are
used, are described on [Godot's website](https://fund.godotengine.org).
used, are described on [Godot's website](https://godotengine.org/donate).
The following is a list of the current monthly donors, who will have their
generous deed immortalized in the next stable release of Godot Engine.
## Patrons
Scorewarrior <https://scwr.gg/godot>
Khronos® Group <https://www.khronos.org/>
OSS Capital <https://oss.capital/>
## Platinum sponsors
JetBrains <https://www.jetbrains.com/lp/rider-godot/>
Scorewarrior <https://scwr.gg/godot>
V-Sekai <https://github.com/V-Sekai>
W4 Games <https://w4games.com/>
## Gold sponsors
Arm <https://www.arm.com/>
Mega Crit <https://www.megacrit.com/>
Prehensile Tales <https://prehensile-tales.com>
Robot Gentleman <http://robotgentleman.com/>
@ -30,323 +30,262 @@ generous deed immortalized in the next stable release of Godot Engine.
## Silver sponsors
Bippinbits <https://bippinbits.com/>
Blobfish Games <https://www.blobfishgames.com/>
Broken Rules <https://brokenrul.es>
Chasing Carrots <https://www.chasing-carrots.com>
Copia Wealth Studios <https://copiawealthstudios.com/>
Evil Trout Inc. <https://eviltrout.com/>
Games by Malcs <https://gamesbymalcs.com/>
LoadComplete <https://loadcomplete.com/>
Null <https://null.com/>
Orbital Knight <https://www.orbitalknight.com/>
Playful Studios <https://playfulstudios.com/>
Re-Logic <https://re-logic.com/>
Sentry <https://sentry.io/welcome/?utm_source=godotengine&utm_medium=paid-community&utm_campaign=gaming-fy26q3-evergreen&utm_content=static-ad-godot-eng-sponsor-trysentry>
## Diamond members
Acerola <https://www.youtube.com/@Acerola_t>
ASIFA-Hollywood <https://www.asifa-hollywood.org/>
Christina Coffin <https://bsky.app/profile/christinacoffin.bsky.social>
Kanda <https://www.kanda.dk>
Dominic Harris <https://wayfarer-games.com/>
Kiri "ExpiredPopsicle" Artemis <https://expiredpopsicle.com/>
Petr Kharitonov <https://petrkharitonov.com/>
Seats.aero <https://seats.aero/>
Sylv <https://rankith.itch.io/unnamed-space-idle-prototype>
And 1 anonymous donor
And 5 anonymous donors
## Titanium members
Adriaan de Jongh <https://adriaan.games>
Basically Games
Deloryan <https://www.deloryan.com/>
Draknek & Friends <https://www.draknek.org/>
Eugene Denisenko <https://craft.sc/>
Garry Newman
Gigabrain AI Reddit Search Engine <https://thegigabrain.com/?utm_source=godot>
Jettelly <https://jettelly.com/>
Justo Delgado Baudí <https://portfolio.mrcdk.com/>
Kenney <https://kenney.nl/>
Lucid Silence Games
Megafauna Games <https://www.megafauna.games/>
Midjiwan AB <https://www.midjiwan.com>
NekTek Games <https://nektek.games/>
Patrick Curry <https://patrickcurry.com/>
PolyMars <https://youtube.com/@PolyMarsLIVE>
Purple Moss Collectors <https://purplemosscollectors.com>
Matthew Hall <https://crossyroad.com/>
PolyMars <https://polymars.dev/>
Purple Moss Collectors <https://purplemosscollectors.com/>
RPG in a Box <https://www.rpginabox.com>
Tiago Magalhães <https://azerkail.github.io/>
Starkandco <https://github.com/Starkandco>
Studio Sunshower <https://www.studiosunshower.com/>
TrampolineTales <https://TrampolineTales.com/>
And 1 anonymous donor
粟二华 (Su Erhua)
And 4 anonymous donors
## Platinum members
@reilaos
Austin Hackett
Andy Touch
BlockImperiumGames (BIG)
Bytten Studio
Caspar Kleijne
Christopher Shifflett
Cody Bentley
Cristian P.
Daniel Cooper
Darrin Massena
DrDeadlock
Emergo Entertainment
Eric Burns
Fabio Alessandrelli
Francis Nguyen
Fresh Fineapple
GrammAcc
HP van Braam
Huge Workshop
iCommitGames
Jason Hamilton
Jeremy Blouir
Jonah Stich
Josh Anthony
k1r4n8
Ludvig Temperli Risan
Matthew Ekenstedt
Memories in 8Bit
Michael Martin
Mike King
Neal Gompa (Conan Kudo)
Nico Ulriksen
Nikita Blizniuk
Raptor85
Rémi Verschelde
Ronnie Cheng
Ryan Heath
Sacha & Solène Waked
ShikadiGum
Silver Creek Entertainment
Stephan Kessler
Stephen Rice
theysayheygreg
Walaber Entertainment
And 8 anonymous donors
And 14 anonymous donors
## Gold members
2 Nerdy Nerds
73unny
80px
A. Friedman
Abigail F.
Admiral Potato
afreytes
AinaVT
Ajat BlackSun
Alex177Alex
alMoo Games
Alnis Smidchens
Alva Majo
Ammerfest
Amritpal Gill
Andrea Monzini
AndreasOM
Andrew Eiche
Andrew Zah
Anfinor Games
Ariya Studio
Antti Vesanen
Arediss
Asher Glick
Axthelm
BangTheWall
Ben Rog-Wilhelm
Ben Sarsgard [Final Screw]
Benito
Benjamin Bridges
Ben Rog-Wilhelm
BetaTester704
Brut
Bryce Dixon
Bäckdahl
c64cosmin
Carl van der Geest
Carlo Cabanilla
Carlo del Mundo
Chaff Games
Chamber of Light, Flower and Essence Incorporated*
Chet Faliszek
Carl van der Geest
Chocolate Software
Chris Backas
Christian Mauduit
Christian Sueiras
Chris Lambson
Christine Elisabeth Koppel
Cindy Trieu
ClarkThyLord
Codex404
Conquintor
cora
Corey Robinson
Crni Medved
Daniel Eichler
Daniel Krafft
David Gehrig
Datzju
David Chen Zhen
David Coles
David Hubber
David Snopek
Deakcor
Delton Ding
DIGITAL ILIAD
dgehrig
Disco Cat
Distorted Realities
DitherDream
Dominic Harris
Dominik Frizel
Don't You Know Who I Am? Inc.
Dosimada
DullyDev
Dustuu
Dylan Dromard
Eamonn Irvine
Edelweiss
eelSkillz
Emily Flion
Ends
Eren Ogrul
Eric Brand
Fail Forward Games
Eric Phy
Faisal Al-Kubaisi (QatariGameDev)
Fanny Pack Studios
Felix Adam
FeralBytes
Francisco Aliaga
Francis Jasmin
Frozen Fractal
GeoScene
Gaudipern
GetIntoGameDev
GlassBrick
Going Loud Studios
Grau
Grzegorz Wereszko
Guangzhou Lingchan
Hampas
Guilherme Cattani
Hayden Oliver
hiulit
Holly Stubbs
https://domi.zip
Huedeane
Ikuti
Illyan
I.M.I.Self
Immaculate Lift Studio
insomniacKoala
Intrepid Marmot LLC
Ione 15
Isaac Clerencia
Isaac Marovitz
Isaac W
Ivan Tabashki
jakemiki
Jam
Jason Cawood
JAX691
jeff compas
Jeff Hungerford
Jesús Chicharro
JezerM
Johannes Wuensch
John Anders Stav
John Brown
John Gabriel
Jonas Yamazaki
Jonathan
Jonathan Bass
Jordan Chap
Josh Jones
Joshua OddBloom
José Canepa
Julian Todd
Justin Laster
Justin Sasso
Kagia Benjamin
Kalydi Balázs
KAR Games
Karl Bittner
Kevin Morrell
Kiryonn
kodebold
KOGA Mitsuhiro (@shiena)
korinVR
Kostya Stankevych
Kristian Kriehl
KyletheDab
Lars Thießen
LavishBehemoth
Lee Ingram
Leo Fruehstueck
Lisandro Lorea (Red Mage Games)
Logan Apple
Los Lecheros Maincreros
LoveCraftStudio.AI
Luca Junge
Luca Vazzano
Luke_Username
Lyaaaaa Games
LyaaaaaGames
m1n1ster
Madison Nicole Videogames
Manul Opus
Mara Huldra
Mara Huldra
Marcos Vinícius Marcon (Krakaton Games)
Marek Belski
Maskerade Games
Martin Šenkeřík
Matthias B.
Meanwhile SRL
Michael Alexsander
Michael Gooch
Miguel RS Gonçalves
Mike Matthews
Miles(Wedomi Games)
Michael Harrington
Modus Ponens
Moshe Harris
Moth Soup
Mr. Byte
Muscarian Softworks
Nassor Paulino da Silva
NEKERAFA
Neuroticfly Games
nezticle
Nicolas Everhart
nikkehtine
Niklas Wahrman
Nitzan Bueno
NojuHD
NotNet
Oathbringer
Officine Pixel
ohanaya3
Okatima AB
ole-luk-oje
Oscar Robin
Osirisa
osje44
ovym
Parade of Rain
Patrick Forringer
Patrick Traynor
Paul Bettner
PeakMaven - Stefan Langwald
Pete Goodwin
Peter Langmayr
Petr Maláč
Phobos001
pirey
Péter Horváth-Lázár
Petr Maláč
pirey
protogames
Rafa Laguna
re:thinc
RedEye Games
Reid Hannaford
@reilaos
Request
Ric Janus Sapasap
re:thinc
Richard Ivánek
Robin Six
Rodz Labs
Roelof Pieters
Robin Ward
Ronny Mühle
Rubén Rüger
Samuel Judd
Santi_FC
Seref Karahan
shazzner
Sheeta Games
Shifty The Dev
Shiny Shinken
Silverclad Studios
Skie Radscale
Snow Diamond
Sofox
Space Kraken Studios
Spencer Chang
Spoony Panda
Stormbrew
Tanner Storment
tenuki
Terry Cavanagh
terry kasey
ThatGamer
Thomas Kurz
Thomas Lobig
Tobias Bocanegra
Tom Langwaldt
Trevor Slocum
tukon
Twirlin' Curtis
Uriel Campos
twitch.tv/RobitussinMD
Tyler C
Urban Protagonist
Vincent Foulon
Vivian Rodríguez Saseta
Vojtech Lacina
Voxel Floof
Watchinofoye
Xelarender
Yannick
zikes
Zoey Smith
嗯大爷
And 117 anonymous donors
And 143 anonymous donors
## Silver and bronze donors

View file

@ -14,7 +14,7 @@ comprehensive set of [common tools](https://godotengine.org/features), so that
users can focus on making games without having to reinvent the wheel. Games can
be exported with one click to a number of platforms, including the major desktop
platforms (Linux, macOS, Windows), mobile platforms (Android, iOS), as well as
Web-based platforms and [consoles](https://godotengine.org/consoles).
Web-based platforms and [consoles](https://docs.godotengine.org/en/latest/tutorials/platform/consoles.html).
## Free, open source and community-driven
@ -27,8 +27,9 @@ not-for-profit.
Before being open sourced in [February 2014](https://github.com/godotengine/godot/commit/0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac),
Godot had been developed by [Juan Linietsky](https://github.com/reduz) and
[Ariel Manzur](https://github.com/punto-) for several years as an in-house
engine, used to publish several work-for-hire titles.
[Ariel Manzur](https://github.com/punto-) (both still maintaining the project)
for several years as an in-house engine, used to publish several work-for-hire
titles.
![Screenshot of a 3D scene in the Godot Engine editor](https://raw.githubusercontent.com/godotengine/godot-design/master/screenshots/editor_tps_demo_1920x1080.jpg)
@ -41,7 +42,7 @@ Official binaries for the Godot editor and the export templates can be found
### Compiling from source
[See the official docs](https://docs.godotengine.org/en/latest/engine_details/development/compiling)
[See the official docs](https://docs.godotengine.org/en/latest/contributing/development/compiling)
for compilation instructions for every supported platform.
## Community and contributing
@ -74,3 +75,4 @@ for more information.
[![Code Triagers Badge](https://www.codetriage.com/godotengine/godot/badges/users.svg)](https://www.codetriage.com/godotengine/godot)
[![Translate on Weblate](https://hosted.weblate.org/widgets/godot-engine/-/godot/svg-badge.svg)](https://hosted.weblate.org/engage/godot-engine/?utm_source=widget)
[![TODOs](https://badgen.net/https/api.tickgit.com/badgen/github.com/godotengine/godot)](https://www.tickgit.com/browse?repo=github.com/godotengine/godot)

View file

@ -2,7 +2,7 @@
from misc.utility.scons_hints import *
EnsureSConsVersion(4, 0)
EnsurePythonVersion(3, 9)
EnsurePythonVersion(3, 8)
# System
import glob
@ -159,69 +159,40 @@ opts = Variables(customs, ARGUMENTS)
# Target build options
opts.Add((["platform", "p"], "Target platform (%s)" % "|".join(platform_list), ""))
opts.Add(
EnumVariable(
"target", "Compilation target", "editor", ["editor", "template_release", "template_debug"], ignorecase=2
)
)
opts.Add(EnumVariable("arch", "CPU architecture", "auto", ["auto"] + architectures, architecture_aliases, ignorecase=2))
opts.Add(EnumVariable("target", "Compilation target", "editor", ("editor", "template_release", "template_debug")))
opts.Add(EnumVariable("arch", "CPU architecture", "auto", ["auto"] + architectures, architecture_aliases))
opts.Add(BoolVariable("dev_build", "Developer build with dev-only debugging code (DEV_ENABLED)", False))
opts.Add(
EnumVariable(
"optimize",
"Optimization level (by default inferred from 'target' and 'dev_build')",
"auto",
["auto", "none", "custom", "debug", "speed", "speed_trace", "size", "size_extra"],
ignorecase=2,
("auto", "none", "custom", "debug", "speed", "speed_trace", "size", "size_extra"),
)
)
opts.Add(BoolVariable("debug_symbols", "Build with debugging symbols", False))
opts.Add(BoolVariable("separate_debug_symbols", "Extract debugging symbols to a separate file", False))
opts.Add(BoolVariable("debug_paths_relative", "Make file paths in debug symbols relative (if supported)", False))
opts.Add(
EnumVariable(
"lto", "Link-time optimization (production builds)", "none", ["none", "auto", "thin", "full"], ignorecase=2
)
)
opts.Add(EnumVariable("lto", "Link-time optimization (production builds)", "none", ("none", "auto", "thin", "full")))
opts.Add(BoolVariable("production", "Set defaults to build Godot for use in production", False))
opts.Add(BoolVariable("threads", "Enable threading support", True))
# Components
opts.Add(BoolVariable("deprecated", "Enable compatibility code for deprecated and removed features", True))
opts.Add(
EnumVariable("precision", "Set the floating-point precision level", "single", ["single", "double"], ignorecase=2)
)
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 decompression and WOFF2 fonts support", True))
opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver on supported platforms", False))
opts.Add(BoolVariable("vulkan", "Enable the Vulkan rendering driver", True))
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("use_volk", "Use the volk library to load the Vulkan loader dynamically", True))
opts.Add(BoolVariable("accesskit", "Enable the AccessKit driver for screen reader support", True))
opts.Add(BoolVariable("sdl", "Enable the SDL3 input driver", True))
opts.Add(
EnumVariable(
"profiler", "Specify the profiler to use", "none", ["none", "tracy", "perfetto", "instruments"], ignorecase=2
)
)
opts.Add(("profiler_path", "Path to the Profiler framework.", ""))
opts.Add(
BoolVariable(
"profiler_sample_callstack",
"Profile random samples application-wide using a callstack based sampler.",
False,
)
)
opts.Add(
BoolVariable(
"profiler_track_memory",
"Profile memory allocations, if the profiler supports it.",
False,
)
)
opts.Add(BoolVariable("disable_exceptions", "Force disabling exception handling code", True))
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
opts.Add(BoolVariable("accesskit", "Use AccessKit C SDK", True))
opts.Add(("accesskit_sdk_path", "Path to the AccessKit C SDK", ""))
# Advanced options
opts.Add(
@ -230,12 +201,11 @@ opts.Add(
)
)
opts.Add(BoolVariable("tests", "Build the unit tests", False))
opts.Add(BoolVariable("fast_unsafe", "Enable unsafe options for faster incremental builds", 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(BoolVariable("compiledb_gen_only", "Exit after building the compilation database", 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.",
@ -243,16 +213,13 @@ opts.Add(
)
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"], ignorecase=2)
)
opts.Add(EnumVariable("warnings", "Level of compilation warnings", "all", ("extra", "all", "moderate", "no")))
opts.Add(BoolVariable("werror", "Treat compiler warnings as errors", False))
opts.Add("extra_suffix", "Custom extra suffix added to the base filename of all generated binary files", "")
opts.Add("object_prefix", "Custom prefix added to the base filename of all generated object files", "")
opts.Add(BoolVariable("vsproj", "Generate a Visual Studio solution", False))
opts.Add("vsproj_name", "Name of the Visual Studio solution", "godot")
opts.Add("import_env_vars", "A comma-separated list of environment variables to copy from the outer environment.", "")
opts.Add(BoolVariable("disable_exceptions", "Force disabling exception handling code", True))
opts.Add(BoolVariable("disable_3d", "Disable 3D nodes for a smaller executable", False))
opts.Add(BoolVariable("disable_advanced_gui", "Disable advanced GUI nodes and behaviors", False))
opts.Add(BoolVariable("disable_physics_2d", "Disable 2D physics nodes and server", False))
@ -260,17 +227,7 @@ opts.Add(BoolVariable("disable_physics_3d", "Disable 3D physics nodes and server
opts.Add(BoolVariable("disable_navigation_2d", "Disable 2D navigation features", False))
opts.Add(BoolVariable("disable_navigation_3d", "Disable 3D navigation features", False))
opts.Add(BoolVariable("disable_xr", "Disable XR nodes and server", False))
opts.Add(BoolVariable("disable_overrides", "Disable project settings overrides (override.cfg)", False))
opts.Add(
BoolVariable(
"disable_path_overrides",
"Disable CLI arguments to override project path/main pack/scene and run scripts (export template only)",
True,
)
)
opts.Add("build_profile", "Path to a file containing a feature build profile", "")
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
opts.Add(BoolVariable("modules_enabled_by_default", "If no, disable all modules except ones explicitly enabled", True))
opts.Add(BoolVariable("no_editor_splash", "Don't use the custom splash screen for the editor", True))
opts.Add(
@ -280,11 +237,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(
"limit_transitive_includes", "Attempt to limit the amount of transitive includes in system headers", True
)
)
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))
@ -298,14 +250,6 @@ opts.Add(
True,
)
)
opts.Add(
EnumVariable(
"library_type",
"Build library type",
"executable",
("executable", "static_library", "shared_library"),
)
)
# Thirdparty libraries
opts.Add(BoolVariable("builtin_brotli", "Use the built-in Brotli library", True))
@ -318,9 +262,7 @@ opts.Add(BoolVariable("builtin_msdfgen", "Use the built-in MSDFgen library", Tru
opts.Add(BoolVariable("builtin_glslang", "Use the built-in glslang library", True))
opts.Add(BoolVariable("builtin_graphite", "Use the built-in Graphite library", True))
opts.Add(BoolVariable("builtin_harfbuzz", "Use the built-in HarfBuzz library", True))
opts.Add(BoolVariable("builtin_sdl", "Use the built-in SDL library", True))
opts.Add(BoolVariable("builtin_icu4c", "Use the built-in ICU library", True))
opts.Add(BoolVariable("builtin_libjpeg_turbo", "Use the built-in libjpeg-turbo library", True))
opts.Add(BoolVariable("builtin_libogg", "Use the built-in libogg library", True))
opts.Add(BoolVariable("builtin_libpng", "Use the built-in libpng library", True))
opts.Add(BoolVariable("builtin_libtheora", "Use the built-in libtheora library", True))
@ -354,9 +296,6 @@ opts.Add("asflags", "Custom flags for the assembler")
opts.Add("arflags", "Custom flags for the archive tool")
opts.Add("rcflags", "Custom flags for Windows resource compiler")
opts.Add("c_compiler_launcher", "C compiler launcher (e.g. `ccache`)")
opts.Add("cpp_compiler_launcher", "C++ compiler launcher (e.g. `ccache`)")
# Update the environment to have all above options defined
# in following code (especially platform and custom_modules).
opts.Update(env)
@ -511,6 +450,16 @@ for tool in custom_tools:
# Add default include paths.
env.Prepend(CPPPATH=["#"])
# Allow marking includes as external/system to avoid raising warnings.
env["_CCCOMCOM"] += " $_CPPEXTINCFLAGS"
env["CPPEXTPATH"] = []
if env.scons_version < (4, 2):
env["_CPPEXTINCFLAGS"] = "${_concat(EXTINCPREFIX, CPPEXTPATH, EXTINCSUFFIX, __env__, RDirs, TARGET, SOURCE)}"
else:
env["_CPPEXTINCFLAGS"] = (
"${_concat(EXTINCPREFIX, CPPEXTPATH, EXTINCSUFFIX, __env__, RDirs, TARGET, SOURCE, affect_signature=False)}"
)
# configure ENV for platform
env.platform_exporters = platform_exporters
env.platform_apis = platform_apis
@ -533,7 +482,7 @@ if env["optimize"] == "auto":
opt_level = "speed_trace"
else: # Release
opt_level = "speed"
env["optimize"] = opt_level
env["optimize"] = ARGUMENTS.get("optimize", opt_level)
env["debug_symbols"] = methods.get_cmdline_bool("debug_symbols", env.dev_build)
@ -562,10 +511,10 @@ env.Decider("MD5-timestamp")
# SCons speed optimization controlled by the `fast_unsafe` option, which provide
# more than 10 s speed up for incremental rebuilds.
# Unsafe as they reduce the certainty of rebuilding all changed files.
# If you use it and run into corrupted incremental builds, try to turn it off.
# Unsafe as they reduce the certainty of rebuilding all changed files, so it's
# enabled by default for `debug` builds, and can be overridden from command line.
# Ref: https://github.com/SCons/scons/wiki/GoFastButton
if env["fast_unsafe"]:
if methods.get_cmdline_bool("fast_unsafe", env.dev_build):
env.SetOption("implicit_cache", 1)
env.SetOption("max_drift", 60)
@ -588,13 +537,6 @@ if not env["deprecated"]:
if env["precision"] == "double":
env.Append(CPPDEFINES=["REAL_T_IS_DOUBLE"])
# Library Support
if env["library_type"] != "executable":
if "library" not in env.get("supported", []):
print_error(f"Library builds unsupported for {env['platform']}")
Exit(255)
env.Append(CPPDEFINES=["LIBGODOT_ENABLED"])
# Default num_jobs to local cpu count if not user specified.
# SCons has a peculiarity where user-specified options won't be overridden
# by SetOption, so we can rely on this to know if we should use our default.
@ -648,11 +590,8 @@ if env["build_profile"] != "":
dbo = ft["disabled_build_options"]
for c in dbo:
env[c] = dbo[c]
except json.JSONDecodeError as err:
print_error(f'Failed to open feature build profile due to JSON decoding error: "{env["build_profile"]}"\n{err}')
Exit(255)
except FileNotFoundError:
print_error(f'Feature build profile not found at: "{env["build_profile"]}"')
except json.JSONDecodeError:
print_error(f'Failed to open feature build profile: "{env["build_profile"]}"')
Exit(255)
# 'dev_mode' and 'production' are aliases to set default options if they haven't been
@ -676,7 +615,6 @@ if env["strict_checks"]:
# Run SCU file generation script if in a SCU build.
if env["scu_build"]:
env.Append(CPPDEFINES=["SCU_BUILD_ENABLED"])
max_includes_per_scu = 8
if env.dev_build:
max_includes_per_scu = 1024
@ -692,11 +630,7 @@ if env["scu_build"]:
# are actually handled to change compile options, etc.
detect.configure(env)
platform_string = env["platform"]
if env.get("simulator"):
platform_string += " (simulator)"
print(f'Building for platform "{platform_string}", architecture "{env["arch"]}", target "{env["target"]}".')
print(f'Building for platform "{env["platform"]}", architecture "{env["arch"]}", target "{env["target"]}".')
if env.dev_build:
print_info("Developer build, with debug optimization level and debug symbols (unless overridden).")
@ -732,11 +666,17 @@ elif methods.using_clang(env):
# Apple LLVM versions differ from upstream LLVM version \o/, compare
# in https://en.wikipedia.org/wiki/Xcode#Toolchain_versions
if methods.is_apple_clang(env):
if cc_version_major < 16:
if cc_version_major < 10:
print_error(
"Detected Apple Clang version older than 16, supported versions are Apple Clang 16 (Xcode 16) and later."
"Detected Apple Clang version older than 10, which does not fully "
"support C++17. Supported versions are Apple Clang 10 and later."
)
Exit(255)
elif env["debug_paths_relative"] and cc_version_major < 12:
print_warning(
"Apple Clang < 12 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option."
)
env["debug_paths_relative"] = False
else:
if cc_version_major < 6:
print_error(
@ -770,26 +710,12 @@ elif env.msvc:
)
Exit(255)
# Set x86 CPU instruction sets to use by the compiler's autovectorization.
if env["arch"] == "x86_64":
# On 64-bit x86, enable SSE 4.2 and prior instruction sets (SSE3/SSSE3/SSE4/SSE4.1) to improve performance.
# This is supported on most CPUs released after 2009-2011 (Intel Nehalem, AMD Bulldozer).
# AVX and AVX2 aren't enabled because they aren't available on more recent low-end Intel CPUs.
if env.msvc and not methods.using_clang(env):
# https://stackoverflow.com/questions/64053597/how-do-i-enable-sse4-1-and-sse3-but-not-avx-in-msvc/69328426
env.Append(CCFLAGS=["/d2archSSE42"])
else:
# `-msse2` is implied when compiling for x86_64.
env.Append(CCFLAGS=["-msse4.2", "-mpopcnt"])
elif env["arch"] == "x86_32":
# Be more conservative with instruction sets on 32-bit x86 to improve compatibility.
# SSE and SSE2 are present on all CPUs that support 64-bit, even if running a 32-bit OS.
if env.msvc and not methods.using_clang(env):
# Default architecture flags.
if env["arch"] == "x86_32":
if env.msvc:
env.Append(CCFLAGS=["/arch:SSE2"])
else:
# Use `-mfpmath=sse` to use SSE for floating-point math, which is more stable than x87.
# `-mstackrealign` is needed for it to work.
env.Append(CCFLAGS=["-msse2", "-mfpmath=sse", "-mstackrealign"])
env.Append(CCFLAGS=["-msse2"])
# Explicitly specify colored output.
if methods.using_gcc(env):
@ -799,13 +725,6 @@ elif methods.using_clang(env) or methods.using_emcc(env):
if sys.platform == "win32":
env.AppendUnique(CCFLAGS=["-fansi-escape-codes"])
# Attempt to reduce transitive includes.
if env["limit_transitive_includes"]:
if not env.msvc:
# FIXME: This define only affects `libcpp`, but lack of guaranteed, granular detection means
# we're better off applying it universally.
env.AppendUnique(CPPDEFINES=["_LIBCPP_REMOVE_TRANSITIVE_INCLUDES"])
# Set optimize and debug_symbols flags.
# "custom" means do nothing and let users set their own optimization flags.
# Needs to happen after configure to have `env.msvc` defined.
@ -956,23 +875,20 @@ if env.msvc and not methods.using_clang(env): # MSVC
else: # GCC, Clang
common_warnings = []
if methods.using_gcc(env):
common_warnings += ["-Wshadow", "-Wno-misleading-indentation"]
if cc_version_major < 11:
# Regression in GCC 9/10, spams so much in our variadic templates
# that we need to outright disable it.
common_warnings += ["-Wno-type-limits"]
if cc_version_major == 12:
# Regression in GCC 12, false positives in our error macros, see GH-58747.
if cc_version_major >= 12: # False positives in our error macros, see GH-58747.
common_warnings += ["-Wno-return-type"]
if cc_version_major >= 11:
common_warnings += ["-Wenum-conversion"]
elif methods.using_clang(env) or methods.using_emcc(env):
common_warnings += ["-Wshadow-field-in-constructor", "-Wshadow-uncaptured-local"]
# We often implement `operator<` for structs of pointers as a requirement
# for putting them in `Set` or `Map`. We don't mind about unreliable ordering.
common_warnings += ["-Wno-ordered-compare-function-pointers"]
common_warnings += ["-Wenum-conversion"]
# clang-cl will interpret `-Wall` as `-Weverything`, workaround with compatibility cast.
env["WARNLEVEL"] = "-Wall" if not env.msvc else "-W3"
@ -1009,6 +925,19 @@ else: # GCC, Clang
if env["werror"]:
env.AppendUnique(CCFLAGS=["-Werror"])
# Configure external includes.
if env.msvc:
if not methods.using_clang(env):
if cc_version_major < 16 or (cc_version_major == 16 and cc_version_minor < 10):
env.AppendUnique(CCFLAGS=["/experimental:external"])
env.AppendUnique(CCFLAGS=["/external:anglebrackets"])
env.AppendUnique(CCFLAGS=["/external:W0"])
env["EXTINCPREFIX"] = "/external:I"
env["EXTINCSUFFIX"] = ""
else:
env["EXTINCPREFIX"] = "-isystem "
env["EXTINCSUFFIX"] = ""
if hasattr(detect, "get_program_suffix"):
suffix = "." + detect.get_program_suffix()
else:
@ -1073,12 +1002,6 @@ if env["minizip"]:
if env["brotli"]:
env.Append(CPPDEFINES=["BROTLI_ENABLED"])
if not env["disable_overrides"]:
env.Append(CPPDEFINES=["OVERRIDE_ENABLED"])
if env.editor_build or not env["disable_path_overrides"]:
env.Append(CPPDEFINES=["OVERRIDE_PATH_ENABLED"])
if not env["verbose"]:
methods.no_verbose(env)
@ -1172,6 +1095,7 @@ env.Append(BUILDERS=GLSL_BUILDERS)
if env["compiledb"]:
env.Tool("compilation_db")
env.Alias("compiledb", env.CompilationDatabase())
env.NoCache(env.CompilationDatabase())
if not env["verbose"]:
env["COMPILATIONDB_COMSTR"] = "$GENCOMSTR"
@ -1198,13 +1122,6 @@ for key in (emitters := env.StaticObject.builder.emitter):
for key in (emitters := env.SharedObject.builder.emitter):
emitters[key] = ListEmitter([methods.redirect_emitter] + env.Flatten(emitters[key]))
# Prepend compiler launchers
if "c_compiler_launcher" in env:
env["CC"] = " ".join([env["c_compiler_launcher"], env["CC"]])
if "cpp_compiler_launcher" in env:
env["CXX"] = " ".join([env["cpp_compiler_launcher"], env["CXX"]])
# Build subdirs, the build order is dependent on link order.
Export("env")
@ -1229,14 +1146,17 @@ if env["vsproj"]:
env["CPPPATH"] = [Dir(path) for path in env["CPPPATH"]]
methods.generate_vs_project(env, ARGUMENTS, env["vsproj_name"])
# Check for the existence of headers
conf = Configure(env)
if "check_c_headers" in env:
headers = env["check_c_headers"]
for header in headers:
if conf.CheckCHeader(header):
env.AppendUnique(CPPDEFINES=[headers[header]])
conf.Finish()
# Miscellaneous & post-build methods.
if not env.GetOption("clean") and not env.GetOption("help"):
if env["compiledb"] and env["compiledb_gen_only"]:
from SCons.Tool.compilation_db import write_compilation_db
write_compilation_db([env.File("compile_commands.json")], [], env)
env.Exit()
methods.dump(env)
methods.show_progress(env)
methods.prepare_purge(env)

View file

@ -1,14 +1,14 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")
import os
import core_builders
import methods
Import("env")
env.core_sources = []
# Add required thirdparty code.
@ -47,14 +47,12 @@ if env["brotli"] and env["builtin_brotli"]:
"dec/bit_reader.c",
"dec/decode.c",
"dec/huffman.c",
"dec/prefix.c",
"dec/state.c",
"dec/static_init.c",
]
thirdparty_brotli_sources = [thirdparty_brotli_dir + file for file in thirdparty_brotli_sources]
env_thirdparty.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"])
env.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"])
env_thirdparty.Prepend(CPPEXTPATH=[thirdparty_brotli_dir + "include"])
env.Prepend(CPPEXTPATH=[thirdparty_brotli_dir + "include"])
if env.get("use_ubsan") or env.get("use_asan") or env.get("use_tsan") or env.get("use_lsan") or env.get("use_msan"):
env_thirdparty.Append(CPPDEFINES=["BROTLI_BUILD_PORTABLE"])
@ -71,8 +69,8 @@ if env["builtin_clipper2"]:
]
thirdparty_clipper_sources = [thirdparty_clipper_dir + file for file in thirdparty_clipper_sources]
env_thirdparty.Prepend(CPPPATH=[thirdparty_clipper_dir + "include"])
env.Prepend(CPPPATH=[thirdparty_clipper_dir + "include"])
env_thirdparty.Prepend(CPPEXTPATH=[thirdparty_clipper_dir + "include"])
env.Prepend(CPPEXTPATH=[thirdparty_clipper_dir + "include"])
env_thirdparty.Append(CPPDEFINES=["CLIPPER2_ENABLED"])
env.Append(CPPDEFINES=["CLIPPER2_ENABLED"])
@ -96,9 +94,9 @@ if env["builtin_zlib"]:
]
thirdparty_zlib_sources = [thirdparty_zlib_dir + file for file in thirdparty_zlib_sources]
env_thirdparty.Prepend(CPPPATH=[thirdparty_zlib_dir])
env_thirdparty.Prepend(CPPEXTPATH=[thirdparty_zlib_dir])
# Needs to be available in main env too
env.Prepend(CPPPATH=[thirdparty_zlib_dir])
env.Prepend(CPPEXTPATH=[thirdparty_zlib_dir])
if env.dev_build:
env_thirdparty.Append(CPPDEFINES=["ZLIB_DEBUG"])
# Affects headers so it should also be defined for Godot code
@ -113,7 +111,9 @@ thirdparty_minizip_sources = ["ioapi.c", "unzip.c", "zip.c"]
thirdparty_minizip_sources = [thirdparty_minizip_dir + file for file in thirdparty_minizip_sources]
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_minizip_sources)
# Zstd library, can be unbundled
# Zstd library, can be unbundled in theory
# though we currently use some private symbols
# https://github.com/godotengine/godot/issues/17374
if env["builtin_zstd"]:
thirdparty_zstd_dir = "#thirdparty/zstd/"
thirdparty_zstd_sources = [
@ -134,7 +134,6 @@ if env["builtin_zstd"]:
"compress/zstd_lazy.c",
"compress/zstd_ldm.c",
"compress/zstd_opt.c",
"compress/zstd_preSplit.c",
"compress/zstdmt_compress.c",
"compress/zstd_compress_literals.c",
"compress/zstd_compress_sequences.c",
@ -144,18 +143,14 @@ if env["builtin_zstd"]:
"decompress/zstd_decompress_block.c",
"decompress/zstd_decompress.c",
]
if (
env["platform"] in ["android", "ios", "linuxbsd", "macos", "windows"]
and env["arch"] == "x86_64"
and not env.msvc
):
if env["platform"] in ["android", "ios", "linuxbsd", "macos"] and env["arch"] == "x86_64":
# Match platforms with ZSTD_ASM_SUPPORTED in common/portability_macros.h
thirdparty_zstd_sources.append("decompress/huf_decompress_amd64.S")
thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
env_thirdparty.Prepend(CPPPATH=[thirdparty_zstd_dir, thirdparty_zstd_dir + "common"])
env_thirdparty.Prepend(CPPEXTPATH=[thirdparty_zstd_dir, thirdparty_zstd_dir + "common"])
env_thirdparty.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"])
env.Prepend(CPPPATH=thirdparty_zstd_dir)
env.Prepend(CPPEXTPATH=thirdparty_zstd_dir)
# Also needed in main env includes will trigger warnings
env.Append(CPPDEFINES=["ZSTD_STATIC_LINKING_ONLY"])
@ -166,44 +161,100 @@ env.core_sources += thirdparty_obj
# Godot source files
env.add_source_files(env.core_sources, "*.cpp")
# Generate disabled classes
env.CommandNoCache(
"disabled_classes.gen.h", env.Value(env.disabled_classes), env.Run(core_builders.disabled_class_builder)
)
def disabled_class_builder(target, source, env):
with methods.generated_wrapper(str(target[0])) as file:
for c in source[0].read():
if cs := c.strip():
file.write(f"#define ClassDB_Disable_{cs} 1\n")
env.CommandNoCache("disabled_classes.gen.h", env.Value(env.disabled_classes), env.Run(disabled_class_builder))
# Generate version info
def version_info_builder(target, source, env):
with methods.generated_wrapper(str(target[0])) as file:
file.write(
"""\
#define GODOT_VERSION_SHORT_NAME "{short_name}"
#define GODOT_VERSION_NAME "{name}"
#define GODOT_VERSION_MAJOR {major}
#define GODOT_VERSION_MINOR {minor}
#define GODOT_VERSION_PATCH {patch}
#define GODOT_VERSION_STATUS "{status}"
#define GODOT_VERSION_BUILD "{build}"
#define GODOT_VERSION_MODULE_CONFIG "{module_config}"
#define GODOT_VERSION_WEBSITE "{website}"
#define GODOT_VERSION_DOCS_BRANCH "{docs_branch}"
#define GODOT_VERSION_DOCS_URL "https://docs.godotengine.org/en/" GODOT_VERSION_DOCS_BRANCH
""".format(**source[0].read())
)
env.CommandNoCache(
"version_generated.gen.h",
env.Value(methods.get_version_info(env.module_version_string)),
env.Run(core_builders.version_info_builder),
env.Run(version_info_builder),
)
# Generate version hash
gen_hash = env.CommandNoCache(
"version_hash.gen.cpp", env.Value(methods.get_git_info()), env.Run(core_builders.version_hash_builder)
)
def version_hash_builder(target, source, env):
with methods.generated_wrapper(str(target[0])) as file:
file.write(
"""\
#include "core/version.h"
const char *const GODOT_VERSION_HASH = "{git_hash}";
const uint64_t GODOT_VERSION_TIMESTAMP = {git_timestamp};
""".format(**source[0].read())
)
gen_hash = env.CommandNoCache("version_hash.gen.cpp", env.Value(methods.get_git_info()), env.Run(version_hash_builder))
env.add_source_files(env.core_sources, gen_hash)
# Generate AES256 script encryption key
encryption_key = os.environ.get("SCRIPT_AES256_ENCRYPTION_KEY")
if encryption_key:
print(
"\n*** IMPORTANT: Compiling Godot with custom `SCRIPT_AES256_ENCRYPTION_KEY` set as environment variable."
"\n*** Make sure to use templates compiled with this key when exporting a project with encryption.\n"
def encryption_key_builder(target, source, env):
with methods.generated_wrapper(str(target[0])) as file:
file.write(
f"""\
#include "core/config/project_settings.h"
uint8_t script_encryption_key[32] = {{
{source[0]}
}};"""
)
gen_encrypt = env.CommandNoCache(
"script_encryption_key.gen.cpp",
env.Value(encryption_key),
env.Run(core_builders.encryption_key_builder),
)
gdkey = os.environ.get("SCRIPT_AES256_ENCRYPTION_KEY", "0" * 64)
ec_valid = len(gdkey) == 64
if ec_valid:
try:
gdkey = ", ".join([str(int(f"{a}{b}", 16)) for a, b in zip(gdkey[0::2], gdkey[1::2])])
except Exception:
ec_valid = False
if not ec_valid:
methods.print_error(
f'Invalid AES256 encryption key, not 64 hexadecimal characters: "{gdkey}".\n'
"Unset `SCRIPT_AES256_ENCRYPTION_KEY` in your environment "
"or make sure that it contains exactly 64 hexadecimal characters."
)
Exit(255)
gen_encrypt = env.CommandNoCache("script_encryption_key.gen.cpp", env.Value(gdkey), env.Run(encryption_key_builder))
env.add_source_files(env.core_sources, gen_encrypt)
# Certificates
env.CommandNoCache(
"#core/io/certs_compressed.gen.h",
["#thirdparty/certs/ca-bundle.crt", env.Value(env["builtin_certs"]), env.Value(env["system_certs_path"])],
["#thirdparty/certs/ca-certificates.crt", env.Value(env["builtin_certs"]), env.Value(env["system_certs_path"])],
env.Run(core_builders.make_certs_header),
)
@ -219,7 +270,6 @@ env.CommandNoCache(
)
# Chain load SCsubs
SConscript("profiling/SCsub")
SConscript("os/SCsub")
SConscript("math/SCsub")
SConscript("crypto/SCsub")

View file

@ -34,45 +34,28 @@
#include "core/config/project_settings.h"
#include "core/donors.gen.h"
#include "core/license.gen.h"
#include "core/object/ref_counted.h"
#include "core/variant/typed_array.h"
#include "core/version.h"
#include "servers/rendering/rendering_device.h"
void Engine::_update_time_scale() {
_time_scale = _user_time_scale * _game_time_scale;
user_ips = MAX(1, ips * _user_time_scale);
max_user_physics_steps_per_frame = MAX(max_physics_steps_per_frame, max_physics_steps_per_frame * _user_time_scale);
}
void Engine::set_physics_ticks_per_second(int p_ips) {
ERR_FAIL_COND_MSG(p_ips <= 0, "Engine iterations per second must be greater than 0.");
ips = p_ips;
_update_time_scale();
}
int Engine::get_physics_ticks_per_second() const {
return ips;
}
int Engine::get_user_physics_ticks_per_second() const {
return user_ips;
}
void Engine::set_max_physics_steps_per_frame(int p_max_physics_steps) {
ERR_FAIL_COND_MSG(p_max_physics_steps <= 0, "Maximum number of physics steps per frame must be greater than 0.");
max_physics_steps_per_frame = p_max_physics_steps;
_update_time_scale();
}
int Engine::get_max_physics_steps_per_frame() const {
return max_physics_steps_per_frame;
}
int Engine::get_user_max_physics_steps_per_frame() const {
return max_user_physics_steps_per_frame;
}
void Engine::set_physics_jitter_fix(double p_threshold) {
if (p_threshold < 0) {
p_threshold = 0;
@ -129,21 +112,11 @@ uint32_t Engine::get_frame_delay() const {
}
void Engine::set_time_scale(double p_scale) {
_game_time_scale = p_scale;
_update_time_scale();
_time_scale = p_scale;
}
double Engine::get_time_scale() const {
return freeze_time_scale ? 0.0 : _game_time_scale;
}
void Engine::set_user_time_scale(double p_scale) {
_user_time_scale = p_scale;
_update_time_scale();
}
double Engine::get_effective_time_scale() const {
return freeze_time_scale ? 0.0 : _time_scale;
return freeze_time_scale ? 0 : _time_scale;
}
double Engine::get_unfrozen_time_scale() const {
@ -251,23 +224,40 @@ String Engine::get_license_text() const {
String Engine::get_architecture_name() const {
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
return "x86_64";
#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
return "x86_32";
#elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
return "arm64";
#elif defined(__arm__) || defined(_M_ARM)
return "arm32";
#elif defined(__riscv)
#if __riscv_xlen == 8
return "rv64";
#elif defined(__powerpc64__)
#else
return "riscv";
#endif
#elif defined(__powerpc__)
#if defined(__powerpc64__)
return "ppc64";
#else
return "ppc";
#endif
#elif defined(__loongarch64)
return "loongarch64";
#elif defined(__wasm64__)
#elif defined(__wasm__)
#if defined(__wasm64__)
return "wasm64";
#elif defined(__wasm32__)
return "wasm32";
#endif
#endif
}
bool Engine::is_abort_on_gpu_errors_enabled() const {
@ -410,6 +400,8 @@ String Engine::get_shader_cache_path() const {
return shader_cache_path;
}
Engine *Engine::singleton = nullptr;
Engine *Engine::get_singleton() {
return singleton;
}

View file

@ -30,13 +30,10 @@
#pragma once
#include "core/string/string_name.h"
#include "core/templates/hash_map.h"
#include "core/os/main_loop.h"
#include "core/string/ustring.h"
#include "core/templates/list.h"
class Object;
class Dictionary;
template <typename T>
class TypedArray;
@ -62,17 +59,13 @@ private:
double _process_step = 0;
int ips = 60;
int user_ips = 60;
double physics_jitter_fix = 0.5;
double _fps = 1;
int _max_fps = 0;
int _audio_output_latency = 0;
double _time_scale = 1.0;
double _game_time_scale = 1.0;
double _user_time_scale = 1.0;
uint64_t _physics_frames = 0;
int max_physics_steps_per_frame = 8;
int max_user_physics_steps_per_frame = 8;
double _physics_interpolation_fraction = 0.0f;
bool abort_on_gpu_errors = false;
bool use_validation_layers = false;
@ -97,7 +90,7 @@ private:
bool _print_header = true;
static inline Engine *singleton = nullptr;
static Engine *singleton;
String write_movie_path;
String shader_cache_path;
@ -108,19 +101,14 @@ private:
bool freeze_time_scale = false;
protected:
void _update_time_scale();
public:
static Engine *get_singleton();
virtual void set_physics_ticks_per_second(int p_ips);
virtual int get_physics_ticks_per_second() const;
virtual int get_user_physics_ticks_per_second() const;
virtual void set_max_physics_steps_per_frame(int p_max_physics_steps);
virtual int get_max_physics_steps_per_frame() const;
virtual int get_user_max_physics_steps_per_frame() const;
void set_physics_jitter_fix(double p_threshold);
double get_physics_jitter_fix() const;
@ -144,8 +132,6 @@ public:
void set_time_scale(double p_scale);
double get_time_scale() const;
void set_user_time_scale(double p_scale);
double get_effective_time_scale() const;
double get_unfrozen_time_scale() const;
void set_print_to_stdout(bool p_enabled);

View file

@ -30,29 +30,28 @@
#include "project_settings.h"
#include "core/core_bind.h" // For Compression enum.
#include "core/input/input_map.h"
#include "core/io/compression.h"
#include "core/io/config_file.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/file_access_pack.h"
#include "core/io/marshalls.h"
#include "core/io/resource_uid.h"
#include "core/object/callable_mp.h"
#include "core/object/class_db.h"
#include "core/object/message_queue.h"
#include "core/object/script_language.h"
#include "core/os/os.h"
#include "core/templates/rb_set.h"
#include "core/variant/typed_array.h"
#include "core/variant/variant_parser.h"
#include "core/version.h"
#ifdef TOOLS_ENABLED
#include "core/config/engine.h"
#include "modules/modules_enabled.gen.h" // IWYU pragma: keep. For mono.
#include "modules/modules_enabled.gen.h" // For mono.
#endif // TOOLS_ENABLED
const String ProjectSettings::PROJECT_DATA_DIR_NAME_SUFFIX = "godot";
ProjectSettings *ProjectSettings::singleton = nullptr;
ProjectSettings *ProjectSettings::get_singleton() {
return singleton;
}
@ -69,7 +68,6 @@ String ProjectSettings::get_resource_path() const {
return resource_path;
}
// This returns paths like "res://.godot/imported".
String ProjectSettings::get_imported_files_path() const {
return get_project_data_path().path_join("imported");
}
@ -89,11 +87,6 @@ const PackedStringArray ProjectSettings::get_required_features() {
// Returns the features supported by this build of Godot. Includes all required features.
const PackedStringArray ProjectSettings::_get_supported_features() {
PackedStringArray features = get_required_features();
#ifdef LIBGODOT_ENABLED
features.append("LibGodot");
#endif
#ifdef MODULE_MONO_ENABLED
features.append("C#");
#endif
@ -243,18 +236,18 @@ void ProjectSettings::set_as_internal(const String &p_name, bool p_internal) {
void ProjectSettings::set_ignore_value_in_docs(const String &p_name, bool p_ignore) {
ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name));
#ifdef DEBUG_ENABLED
#ifdef DEBUG_METHODS_ENABLED
props[p_name].ignore_value_in_docs = p_ignore;
#endif // DEBUG_ENABLED
#endif
}
bool ProjectSettings::get_ignore_value_in_docs(const String &p_name) const {
ERR_FAIL_COND_V_MSG(!props.has(p_name), false, vformat("Request for nonexistent project setting: '%s'.", p_name));
#ifdef DEBUG_ENABLED
#ifdef DEBUG_METHODS_ENABLED
return props[p_name].ignore_value_in_docs;
#else
return false;
#endif // DEBUG_ENABLED
#endif
}
void ProjectSettings::add_hidden_prefix(const String &p_prefix) {
@ -288,17 +281,10 @@ String ProjectSettings::globalize_path(const String &p_path) const {
bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
_THREAD_SAFE_METHOD_
// Early return if value hasn't changed (unless it's being deleted)
if (p_value.get_type() != Variant::NIL) {
if (props.has(p_name) && props[p_name].variant == p_value) {
return true;
}
}
if (p_value.get_type() == Variant::NIL) {
props.erase(p_name);
if (p_name.operator String().begins_with("autoload/")) {
String node_name = p_name.operator String().get_slicec('/', 1);
String node_name = p_name.operator String().split("/")[1];
if (autoloads.has(node_name)) {
remove_autoload(node_name);
}
@ -314,9 +300,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
for (int i = 0; i < custom_feature_array.size(); i++) {
custom_features.insert(custom_feature_array[i]);
}
_version++;
_queue_changed(p_name);
_queue_changed();
return true;
}
@ -343,20 +327,8 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
} else {
props[p_name] = VariantContainer(p_value, last_order++);
}
if (p_name.operator String().begins_with("autoload_prepend/")) {
String node_name = p_name.operator String().get_slicec('/', 1);
AutoloadInfo autoload;
autoload.name = node_name;
String path = p_value;
if (path.begins_with("*")) {
autoload.is_singleton = true;
autoload.path = path.substr(1).simplify_path();
} else {
autoload.path = path.simplify_path();
}
add_autoload(autoload, true);
} else if (p_name.operator String().begins_with("autoload/")) {
String node_name = p_name.operator String().get_slicec('/', 1);
if (p_name.operator String().begins_with("autoload/")) {
String node_name = p_name.operator String().split("/")[1];
AutoloadInfo autoload;
autoload.name = node_name;
String path = p_value;
@ -373,8 +345,7 @@ bool ProjectSettings::_set(const StringName &p_name, const Variant &p_value) {
}
}
_version++;
_queue_changed(p_name);
_queue_changed();
return true;
}
@ -451,7 +422,6 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const {
_THREAD_SAFE_METHOD_
RBSet<_VCSort> vclist;
HashMap<String, LocalVector<_VCSort>> setting_overrides;
for (const KeyValue<StringName, VariantContainer> &E : props) {
const VariantContainer *v = &E.value;
@ -492,76 +462,33 @@ void ProjectSettings::_get_property_list(List<PropertyInfo> *p_list) const {
if (v->restart_if_changed) {
vc.flags |= PROPERTY_USAGE_RESTART_IF_CHANGED;
}
int dot = vc.name.rfind_char('.');
if (dot != -1) {
StringName n = vc.name.substr(0, dot);
if (props.has(n)) {
// Property is an override.
setting_overrides[n].push_back(vc);
} else {
vclist.insert(vc);
}
} else {
vclist.insert(vc);
}
for (const _VCSort &E : vclist) {
String prop_info_name = E.name;
int dot = prop_info_name.find_char('.');
if (dot != -1 && !custom_prop_info.has(prop_info_name)) {
prop_info_name = prop_info_name.substr(0, dot);
}
for (const _VCSort &base : vclist) {
if (custom_prop_info.has(base.name)) {
PropertyInfo pi = custom_prop_info[base.name];
pi.name = base.name;
pi.usage = base.flags;
p_list->push_back(pi);
#ifdef TOOLS_ENABLED
} else if (base.name.begins_with(EDITOR_SETTING_OVERRIDE_PREFIX)) {
PropertyInfo info(base.type, base.name, PROPERTY_HINT_NONE, "", base.flags);
const PropertyInfo *pi = editor_settings_info.getptr(base.name.trim_prefix(EDITOR_SETTING_OVERRIDE_PREFIX));
if (pi) {
info.usage = pi->usage;
info.hint = pi->hint;
info.hint_string = pi->hint_string;
}
p_list->push_back(info);
#endif
} else {
p_list->push_back(PropertyInfo(base.type, base.name, PROPERTY_HINT_NONE, "", base.flags));
}
if (setting_overrides.has(base.name)) {
for (const _VCSort &over : setting_overrides.get(base.name)) {
if (custom_prop_info.has(over.name)) {
PropertyInfo pi = custom_prop_info[over.name];
pi.name = over.name;
pi.usage = over.flags;
p_list->push_back(pi);
} else if (custom_prop_info.has(base.name)) {
// Fallback to base property info.
PropertyInfo pi = custom_prop_info[base.name];
pi.name = over.name;
pi.usage = over.flags;
if (custom_prop_info.has(prop_info_name)) {
PropertyInfo pi = custom_prop_info[prop_info_name];
pi.name = E.name;
pi.usage = E.flags;
p_list->push_back(pi);
} else {
p_list->push_back(PropertyInfo(over.type, over.name, PROPERTY_HINT_NONE, "", over.flags));
}
}
p_list->push_back(PropertyInfo(E.type, E.name, PROPERTY_HINT_NONE, "", E.flags));
}
}
}
void ProjectSettings::_queue_changed(const StringName &p_name) {
changed_settings.insert(p_name);
if (!MessageQueue::get_singleton() || MessageQueue::get_singleton()->get_max_buffer_usage() == 0) {
void ProjectSettings::_queue_changed() {
if (is_changed || !MessageQueue::get_singleton() || MessageQueue::get_singleton()->get_max_buffer_usage() == 0) {
return;
}
// Only queue the deferred call once per frame.
if (!is_changed) {
is_changed = true;
callable_mp(this, &ProjectSettings::_emit_changed).call_deferred();
}
}
void ProjectSettings::_emit_changed() {
@ -569,12 +496,7 @@ void ProjectSettings::_emit_changed() {
return;
}
is_changed = false;
// Emit the general settings_changed signal to indicate changes are complete.
emit_signal("settings_changed");
// Clear the changed settings after emitting the signal
changed_settings.clear();
}
bool ProjectSettings::load_resource_pack(const String &p_pack, bool p_replace_files, int p_offset) {
@ -636,13 +558,6 @@ void ProjectSettings::_convert_to_last_version(int p_from_version) {
E.value.variant = action;
}
}
} else if (p_from_version <= 6) {
// Check if we still have legacy boot splash (removed in 4.6), map it to new project setting, then remove legacy setting.
if (has_setting("application/boot_splash/fullsize")) {
// See RenderingServerEnums::SplashStretchMode.
set_setting("application/boot_splash/stretch_mode", get_setting("application/boot_splash/fullsize") ? 1 : 0);
set_setting("application/boot_splash/fullsize", Variant());
}
}
#endif // DISABLE_DEPRECATED
}
@ -662,14 +577,13 @@ void ProjectSettings::_convert_to_last_version(int p_from_version) {
* appending '.pck' to the binary name (e.g. 'linux_game' -> 'linux_game.pck').
* o PCK with the same basename as the binary in the current working directory.
* Same as above for the two possible PCK file names.
* - On Android, look for 'assets.sparsepck' and try loading it, if it doesn't work,
* proceed to the next step.
* - On relevant platforms (Android/iOS), lookup project file in OS resource path.
* If found, load it or fail.
* - Lookup project file in passed `p_path` (--path passed by the user), i.e. we
* are running from source code.
* If not found and `p_upwards` is true, look for project files in parent folders
* up to the system root (used to run a game from command line while in a subfolder).
* If not found and `p_upwards` is true (--upwards passed by the user), look for
* project files in parent folders up to the system root (used to run a game
* from command line while in a subfolder).
* If a project file is found, load it or fail.
* If nothing was found, error out.
*/
@ -690,16 +604,11 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
ERR_FAIL_COND_V_MSG(!ok, ERR_CANT_OPEN, vformat("Cannot open resource pack '%s'.", p_main_pack));
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
#ifdef OVERRIDE_ENABLED
if (err == OK && !p_ignore_override) {
// Load override from location of the main pack
// Optional, we don't mind if it fails
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
if (!disable_override) {
_load_settings_text(p_main_pack.get_base_dir().path_join("override.cfg"));
}
}
#endif // OVERRIDE_ENABLED
return err;
}
@ -723,7 +632,7 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
// We need to test both possibilities as extensions for Linux binaries are optional
// (so both 'mygame.bin' and 'mygame' should be able to find 'mygame.pck').
#if defined(MACOS_ENABLED) || defined(APPLE_EMBEDDED_ENABLED)
#ifdef MACOS_ENABLED
if (!found) {
// Attempt to load PCK from macOS .app bundle resources.
found = _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().path_join(exec_basename + ".pck"), false, 0, true) || _load_resource_pack(OS::get_singleton()->get_bundle_resource_dir().path_join(exec_filename + ".pck"), false, 0, true);
@ -745,44 +654,29 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
// If we opened our package, try and load our project.
if (found) {
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
#ifdef OVERRIDE_ENABLED
if (err == OK && !p_ignore_override) {
// Load overrides from the PCK and the executable location.
// Optional, we don't mind if either fails.
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
if (!disable_override) {
_load_settings_text("res://override.cfg");
_load_settings_text(exec_path.get_base_dir().path_join("override.cfg"));
}
}
#endif // OVERRIDE_ENABLED
return err;
}
}
#ifdef ANDROID_ENABLED
// Attempt to load sparse PCK assets.
_load_resource_pack("res://assets.sparsepck", false, 0, true);
#endif
// Try to use the filesystem for files, according to OS.
// (Only Android -when reading from PCK-.)
// (Only Android -when reading from pck- and iOS use this.)
if (!OS::get_singleton()->get_resource_dir().is_empty()) {
Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary");
#ifdef OVERRIDE_ENABLED
if (err == OK && !p_ignore_override) {
// Optional, we don't mind if it fails.
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
if (!disable_override) {
_load_settings_text("res://override.cfg");
}
}
#endif // OVERRIDE_ENABLED
return err;
}
#if defined(MACOS_ENABLED) || defined(APPLE_EMBEDDED_ENABLED)
#ifdef MACOS_ENABLED
// Attempt to load project file from macOS .app bundle resources.
resource_path = OS::get_singleton()->get_bundle_resource_dir();
if (!resource_path.is_empty()) {
@ -798,16 +692,11 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
err = _load_settings_text_or_binary(resource_path.path_join("project.godot"), resource_path.path_join("project.binary"));
if (err == OK && !p_ignore_override) {
// Optional, we don't mind if it fails.
#ifdef OVERRIDE_ENABLED
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
if (!disable_override) {
_load_settings_text(resource_path.path_join("override.cfg"));
}
#endif // OVERRIDE_ENABLED
return err;
}
}
#endif // MACOS_ENABLED
#endif
// Nothing was found, try to find a project file in provided path (`p_path`)
// or, if requested (`p_upwards`) in parent directories.
@ -825,21 +714,13 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
resource_path = current_dir;
resource_path = resource_path.replace_char('\\', '/'); // Windows path to Unix path just in case.
err = _load_settings_text_or_binary(current_dir.path_join("project.godot"), current_dir.path_join("project.binary"));
if (err == OK) {
#ifdef OVERRIDE_ENABLED
if (!p_ignore_override) {
if (err == OK && !p_ignore_override) {
// Optional, we don't mind if it fails.
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
if (!disable_override) {
_load_settings_text(current_dir.path_join("override.cfg"));
}
}
#endif // OVERRIDE_ENABLED
found = true;
break;
}
#if defined(OVERRIDE_PATH_ENABLED)
if (p_upwards) {
// Try to load settings ascending through parent directories
d->change_dir("..");
@ -848,9 +729,6 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
}
current_dir = d->get_current_dir();
} else {
#else
{
#endif
break;
}
}
@ -868,17 +746,12 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b
Error ProjectSettings::setup(const String &p_path, const String &p_main_pack, bool p_upwards, bool p_ignore_override) {
Error err = _setup(p_path, p_main_pack, p_upwards, p_ignore_override);
#ifdef OVERRIDE_ENABLED
if (err == OK && !p_ignore_override) {
bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override");
if (!disable_override) {
String custom_settings = GLOBAL_GET("application/config/project_settings_override");
if (!custom_settings.is_empty()) {
_load_settings_text(custom_settings);
}
}
}
#endif
// Updating the default value after the project settings have loaded.
bool use_hidden_directory = GLOBAL_GET("application/config/use_hidden_project_data_directory");
@ -921,7 +794,7 @@ Error ProjectSettings::_load_settings_binary(const String &p_path) {
for (uint32_t i = 0; i < count; i++) {
uint32_t slen = f->get_32();
CharString cs;
cs.resize_uninitialized(slen + 1);
cs.resize(slen + 1);
cs[slen] = 0;
f->get_buffer((uint8_t *)cs.ptr(), slen);
String key = String::utf8(cs.ptr(), slen);
@ -1006,21 +879,6 @@ Error ProjectSettings::_load_settings_text_or_binary(const String &p_text_path,
// Fallback to text-based project.godot file if binary was not found.
err = _load_settings_text(p_text_path);
if (err == OK) {
#ifndef DISABLE_DEPRECATED
const PackedStringArray features = get_setting("application/config/features");
for (const String &feat : features) {
if (feat.contains_char('.') && feat.get_slice_count(".") == 2) {
int major_version = feat.get_slicec('.', 0).to_int();
int minor_version = feat.get_slicec('.', 1).to_int();
// Major version is irrelevant, but the extra check ensures that the feature is in fact a version string.
if (major_version == 4 && minor_version < 6) {
// Enable MeshInstance3D compat for projects created before 4.6.
set_setting("animation/compatibility/default_parent_skeleton_in_mesh_instance_3d", true);
}
break;
}
}
#endif
return OK;
} else if (err != ERR_FILE_NOT_FOUND) {
ERR_PRINT(vformat("Couldn't load file '%s', error code %d.", p_text_path, err));
@ -1062,7 +920,6 @@ bool ProjectSettings::is_builtin_setting(const String &p_name) const {
void ProjectSettings::clear(const String &p_name) {
ERR_FAIL_COND_MSG(!props.has(p_name), vformat("Request for nonexistent project setting: '%s'.", p_name));
props.erase(p_name);
_queue_changed(p_name);
}
Error ProjectSettings::save() {
@ -1346,12 +1203,8 @@ Variant _GLOBAL_DEF(const PropertyInfo &p_info, const Variant &p_default, bool p
}
void ProjectSettings::_add_property_info_bind(const Dictionary &p_info) {
ERR_FAIL_COND_MSG(!p_info.has("name"), "Property info is missing \"name\" field.");
ERR_FAIL_COND_MSG(!p_info.has("type"), "Property info is missing \"type\" field.");
if (p_info.has("usage")) {
WARN_PRINT("\"usage\" is not supported in add_property_info().");
}
ERR_FAIL_COND(!p_info.has("name"));
ERR_FAIL_COND(!p_info.has("type"));
PropertyInfo pinfo;
pinfo.name = p_info["name"];
@ -1388,7 +1241,7 @@ bool ProjectSettings::is_project_loaded() const {
}
bool ProjectSettings::_property_can_revert(const StringName &p_name) const {
return props.has(p_name) && !String(p_name).begins_with(EDITOR_SETTING_OVERRIDE_PREFIX);
return props.has(p_name);
}
bool ProjectSettings::_property_get_revert(const StringName &p_name, Variant &r_property) const {
@ -1412,23 +1265,6 @@ Variant ProjectSettings::get_setting(const String &p_setting, const Variant &p_d
}
}
PackedStringArray ProjectSettings::get_changed_settings() const {
PackedStringArray arr;
for (const StringName &setting : changed_settings) {
arr.push_back(setting);
}
return arr;
}
bool ProjectSettings::check_changed_settings_in_group(const String &p_setting_prefix) const {
for (const StringName &setting : changed_settings) {
if (String(setting).begins_with(p_setting_prefix)) {
return true;
}
}
return false;
}
void ProjectSettings::refresh_global_class_list() {
// This is called after mounting a new PCK file to pick up class changes.
is_global_class_list_loaded = false; // Make sure we read from the freshly mounted PCK.
@ -1486,16 +1322,9 @@ const HashMap<StringName, ProjectSettings::AutoloadInfo> &ProjectSettings::get_a
return autoloads;
}
void ProjectSettings::add_autoload(const AutoloadInfo &p_autoload, bool p_front_insert) {
void ProjectSettings::add_autoload(const AutoloadInfo &p_autoload) {
ERR_FAIL_COND_MSG(p_autoload.name == StringName(), "Trying to add autoload with no name.");
if (p_front_insert) {
if (autoloads.has(p_autoload.name)) {
autoloads.erase(p_autoload.name);
}
autoloads.insert(p_autoload.name, p_autoload, true);
} else {
autoloads[p_autoload.name] = p_autoload;
}
}
void ProjectSettings::remove_autoload(const StringName &p_autoload) {
@ -1512,12 +1341,6 @@ ProjectSettings::AutoloadInfo ProjectSettings::get_autoload(const StringName &p_
return autoloads[p_name];
}
void ProjectSettings::fix_autoload_paths() {
for (KeyValue<StringName, AutoloadInfo> &kv : autoloads) {
kv.value.path = ResourceUID::ensure_path(kv.value.path);
}
}
const HashMap<StringName, String> &ProjectSettings::get_global_groups_list() const {
return global_groups;
}
@ -1568,7 +1391,8 @@ void ProjectSettings::load_scene_groups_cache() {
Ref<ConfigFile> cf;
cf.instantiate();
if (cf->load(get_scene_groups_cache_path()) == OK) {
Vector<String> scene_paths = cf->get_sections();
List<String> scene_paths;
cf->get_sections(&scene_paths);
for (const String &E : scene_paths) {
Array scene_groups = cf->get_value(E, "groups", Array());
HashSet<StringName> cache;
@ -1604,18 +1428,6 @@ void ProjectSettings::get_argument_options(const StringName &p_function, int p_i
}
#endif
void ProjectSettings::set_editor_setting_override(const String &p_setting, const Variant &p_value) {
set_setting(EDITOR_SETTING_OVERRIDE_PREFIX + p_setting, p_value);
}
bool ProjectSettings::has_editor_setting_override(const String &p_setting) const {
return has_setting(EDITOR_SETTING_OVERRIDE_PREFIX + p_setting);
}
Variant ProjectSettings::get_editor_setting_override(const String &p_setting) const {
return get_setting(EDITOR_SETTING_OVERRIDE_PREFIX + p_setting);
}
void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_setting", "name"), &ProjectSettings::has_setting);
ClassDB::bind_method(D_METHOD("set_setting", "name", "value"), &ProjectSettings::set_setting);
@ -1638,15 +1450,12 @@ void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("save_custom", "file"), &ProjectSettings::_save_custom_bnd);
// Change tracking methods
ClassDB::bind_method(D_METHOD("get_changed_settings"), &ProjectSettings::get_changed_settings);
ClassDB::bind_method(D_METHOD("check_changed_settings_in_group", "setting_prefix"), &ProjectSettings::check_changed_settings_in_group);
ADD_SIGNAL(MethodInfo("settings_changed"));
}
void ProjectSettings::_add_builtin_input_map() {
if (InputMap::get_singleton()) {
HashMap<String, List<Ref<InputEvent>>> builtins(InputMap::get_singleton()->get_builtins());
HashMap<String, List<Ref<InputEvent>>> builtins = InputMap::get_singleton()->get_builtins();
for (KeyValue<String, List<Ref<InputEvent>>> &E : builtins) {
Array events;
@ -1688,7 +1497,7 @@ ProjectSettings::ProjectSettings() {
#endif
GLOBAL_DEF_BASIC("application/config/name", "");
GLOBAL_DEF(PropertyInfo(Variant::DICTIONARY, "application/config/name_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary());
GLOBAL_DEF_BASIC(PropertyInfo(Variant::DICTIONARY, "application/config/name_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary());
GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "application/config/description", PROPERTY_HINT_MULTILINE_TEXT), "");
GLOBAL_DEF_BASIC("application/config/version", "");
GLOBAL_DEF_INTERNAL(PropertyInfo(Variant::STRING, "application/config/tags"), PackedStringArray());
@ -1701,7 +1510,6 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("application/config/use_custom_user_dir", false);
GLOBAL_DEF("application/config/custom_user_dir_name", "");
GLOBAL_DEF("application/config/project_settings_override", "");
GLOBAL_DEF("application/config/disable_project_settings_override", false);
GLOBAL_DEF("application/run/main_loop_type", "SceneTree");
GLOBAL_DEF("application/config/auto_accept_quit", true);
@ -1709,7 +1517,6 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "accessibility/general/accessibility_support", PROPERTY_HINT_ENUM, "Auto (When Screen Reader is Running),Always Active,Disabled"), 0);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "accessibility/general/updates_per_second", PROPERTY_HINT_RANGE, "1,100,1"), 60);
GLOBAL_DEF(PropertyInfo(Variant::STRING, "accessibility/general/accessibility_driver", PROPERTY_HINT_ENUM, "accesskit,dummy"), "accesskit");
// The default window size is tuned to:
// - Have a 16:9 aspect ratio,
@ -1739,14 +1546,9 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF(PropertyInfo(Variant::INT, "display/window/size/window_width_override", PROPERTY_HINT_RANGE, "0,7680,1,or_greater"), 0); // 8K resolution
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/hdr/request_hdr_output", false);
GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true);
GLOBAL_DEF("animation/warnings/check_invalid_track_paths", true);
GLOBAL_DEF("animation/warnings/check_angle_interpolation_type_conflicting", true);
#ifndef DISABLE_DEPRECATED
GLOBAL_DEF_RST("animation/compatibility/default_parent_skeleton_in_mesh_instance_3d", false);
#endif
GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "audio/buses/default_bus_layout", PROPERTY_HINT_FILE, "*.tres"), "res://default_bus_layout.tres");
GLOBAL_DEF(PropertyInfo(Variant::INT, "audio/general/default_playback_type", PROPERTY_HINT_ENUM, "Stream,Sample"), 0);
@ -1760,10 +1562,10 @@ ProjectSettings::ProjectSettings() {
_add_builtin_input_map();
// Keep the enum values in sync with the `DisplayServerEnums::ScreenOrientation` enum.
// Keep the enum values in sync with the `DisplayServer::ScreenOrientation` enum.
custom_prop_info["display/window/handheld/orientation"] = PropertyInfo(Variant::INT, "display/window/handheld/orientation", PROPERTY_HINT_ENUM, "Landscape,Portrait,Reverse Landscape,Reverse Portrait,Sensor Landscape,Sensor Portrait,Sensor");
GLOBAL_DEF("display/window/subwindows/embed_subwindows", true);
// Keep the enum values in sync with the `DisplayServerEnums::VSyncMode` enum.
// Keep the enum values in sync with the `DisplayServer::VSyncMode` enum.
custom_prop_info["display/window/vsync/vsync_mode"] = PropertyInfo(Variant::INT, "display/window/vsync/vsync_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Adaptive,Mailbox");
GLOBAL_DEF("display/window/frame_pacing/android/enable_frame_pacing", true);
@ -1813,9 +1615,7 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("gui/timers/tooltip_delay_sec.editor_hint", 0.5);
#endif
GLOBAL_DEF("gui/common/drag_threshold", 10);
GLOBAL_DEF_BASIC("gui/common/snap_controls_to_pixels", true);
GLOBAL_DEF(PropertyInfo(Variant::INT, "gui/common/show_focus_state_on_pointer_event", PROPERTY_HINT_ENUM, "Never,Control Supports Keyboard Input,Always"), 1);
GLOBAL_DEF_BASIC("gui/fonts/dynamic_fonts/use_oversampling", true);
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/vsync/frame_queue_size", PROPERTY_HINT_RANGE, "2,3,1"), 2);
@ -1828,16 +1628,18 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "rendering/rendering_device/pipeline_cache/save_chunk_size_mb", PROPERTY_HINT_RANGE, "0.000001,64.0,0.001,or_greater"), 3.0);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/rendering_device/vulkan/max_descriptors_per_pool", PROPERTY_HINT_RANGE, "1,256,1,or_greater"), 64);
GLOBAL_DEF_RST("rendering/rendering_device/d3d12/max_resource_descriptors", 65536);
custom_prop_info["rendering/rendering_device/d3d12/max_resource_descriptors"] = PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/max_resource_descriptors", PROPERTY_HINT_RANGE, "512,1000000");
GLOBAL_DEF_RST("rendering/rendering_device/d3d12/max_sampler_descriptors", 1024);
custom_prop_info["rendering/rendering_device/d3d12/max_sampler_descriptors"] = PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/max_sampler_descriptors", PROPERTY_HINT_RANGE, "256,2048");
GLOBAL_DEF_RST("rendering/rendering_device/d3d12/max_resource_descriptors_per_frame", 16384);
custom_prop_info["rendering/rendering_device/d3d12/max_resource_descriptors_per_frame"] = PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/max_resource_descriptors_per_frame", PROPERTY_HINT_RANGE, "512,262144");
GLOBAL_DEF_RST("rendering/rendering_device/d3d12/max_sampler_descriptors_per_frame", 1024);
custom_prop_info["rendering/rendering_device/d3d12/max_sampler_descriptors_per_frame"] = PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/max_sampler_descriptors_per_frame", PROPERTY_HINT_RANGE, "256,2048");
GLOBAL_DEF_RST("rendering/rendering_device/d3d12/max_misc_descriptors_per_frame", 512);
custom_prop_info["rendering/rendering_device/d3d12/max_misc_descriptors_per_frame"] = PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/max_misc_descriptors_per_frame", PROPERTY_HINT_RANGE, "32,4096");
// The default value must match the minor part of the Agility SDK version
// installed by the scripts provided in the repository
// (check `misc/scripts/install_d3d12_sdk_windows.py`).
// For example, if the script installs 1.618.5, the default value must be 618.
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/agility_sdk_version", PROPERTY_HINT_RANGE, "0,10000,1,or_greater,hide_control"), 618);
// For example, if the script installs 1.613.3, the default value must be 613.
GLOBAL_DEF_RST(PropertyInfo(Variant::INT, "rendering/rendering_device/d3d12/agility_sdk_version", PROPERTY_HINT_RANGE, "0,10000,1,or_greater,hide_slider"), 613);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,Linear Mipmap,Nearest Mipmap"), 1);
GLOBAL_DEF_BASIC(PropertyInfo(Variant::INT, "rendering/textures/canvas_textures/default_texture_repeat", PROPERTY_HINT_ENUM, "Disable,Enable,Mirror"), 0);
@ -1860,7 +1662,6 @@ ProjectSettings::ProjectSettings() {
#if !defined(NAVIGATION_2D_DISABLED) || !defined(NAVIGATION_3D_DISABLED)
GLOBAL_DEF("navigation/world/map_use_async_iterations", true);
GLOBAL_DEF("navigation/world/region_use_async_iterations", true);
GLOBAL_DEF("navigation/avoidance/thread_model/avoidance_use_multiple_threads", true);
GLOBAL_DEF("navigation/avoidance/thread_model/avoidance_use_high_priority_threads", true);
@ -1871,14 +1672,6 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("navigation/baking/thread_model/baking_use_multiple_threads", true);
GLOBAL_DEF("navigation/baking/thread_model/baking_use_high_priority_threads", true);
#endif // !defined(NAVIGATION_2D_DISABLED) || !defined(NAVIGATION_3D_DISABLED)
#ifndef NAVIGATION_2D_DISABLED
GLOBAL_DEF("navigation/2d/warnings/navmesh_edge_merge_errors", true);
GLOBAL_DEF("navigation/2d/warnings/navmesh_cell_size_mismatch", true);
#endif // NAVIGATION_2D_DISABLED
#ifndef NAVIGATION_3D_DISABLED
GLOBAL_DEF("navigation/3d/warnings/navmesh_edge_merge_errors", true);
GLOBAL_DEF("navigation/3d/warnings/navmesh_cell_size_mismatch", true);
#endif // NAVIGATION_3D_DISABLED
ProjectSettings::get_singleton()->add_hidden_prefix("input/");
}

View file

@ -30,9 +30,7 @@
#pragma once
#include "core/object/object.h"
#include "core/os/thread_safe.h"
#include "core/templates/rb_map.h"
#include "core/object/class_db.h"
template <typename T>
class TypedArray;
@ -44,18 +42,9 @@ class ProjectSettings : public Object {
bool is_changed = false;
// Starting version from 1 ensures that all callers can reset their tested version to 0,
// and will always detect the initial project settings as a "change".
uint32_t _version = 1;
// Track changed settings for get_changed_settings functionality
HashSet<StringName> changed_settings;
public:
typedef HashMap<String, Variant> CustomMap;
// This constant is used to make the ".godot" folder and paths like "res://.godot/editor".
static inline const String PROJECT_DATA_DIR_NAME_SUFFIX = "godot";
static inline const String EDITOR_SETTING_OVERRIDE_PREFIX = PNAME("editor_overrides") + String("/");
static const String PROJECT_DATA_DIR_NAME_SUFFIX;
// Properties that are not for built in values begin from this value, so builtin ones are displayed first.
constexpr static const int32_t NO_BUILTIN_ORDER_BASE = 1 << 16;
@ -81,9 +70,9 @@ protected:
Variant initial;
bool hide_from_editor = false;
bool restart_if_changed = false;
#ifdef DEBUG_ENABLED
#ifdef DEBUG_METHODS_ENABLED
bool ignore_value_in_docs = false;
#endif // DEBUG_ENABLED
#endif
VariantContainer() {}
@ -124,10 +113,10 @@ protected:
bool _property_can_revert(const StringName &p_name) const;
bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
void _queue_changed(const StringName &p_name);
void _queue_changed();
void _emit_changed();
static inline ProjectSettings *singleton = nullptr;
static ProjectSettings *singleton;
Error _load_settings_text(const String &p_path);
Error _load_settings_binary(const String &p_path);
@ -160,10 +149,6 @@ protected:
public:
static const int CONFIG_VERSION = 5;
#ifdef TOOLS_ENABLED
HashMap<String, PropertyInfo> editor_settings_info;
#endif
void set_setting(const String &p_setting, const Variant &p_value);
Variant get_setting(const String &p_setting, const Variant &p_default_value = Variant()) const;
TypedArray<Dictionary> get_global_class_list();
@ -205,7 +190,7 @@ public:
const HashMap<StringName, PropertyInfo> &get_custom_property_info() const;
uint64_t get_last_saved_time() { return last_save_time; }
List<String> get_input_presets() const { return List<String>(input_presets); }
List<String> get_input_presets() const { return input_presets; }
Variant get_setting_with_override(const StringName &p_name) const;
Variant get_setting_with_override_and_custom_features(const StringName &p_name, const Vector<String> &p_features) const;
@ -215,16 +200,11 @@ public:
bool has_custom_feature(const String &p_feature) const;
// Change tracking methods
PackedStringArray get_changed_settings() const;
bool check_changed_settings_in_group(const String &p_setting_prefix) const;
const HashMap<StringName, AutoloadInfo> &get_autoload_list() const;
void add_autoload(const AutoloadInfo &p_autoload, bool p_front_insert = false);
void add_autoload(const AutoloadInfo &p_autoload);
void remove_autoload(const StringName &p_autoload);
bool has_autoload(const StringName &p_autoload) const;
AutoloadInfo get_autoload(const StringName &p_name) const;
void fix_autoload_paths();
const HashMap<StringName, String> &get_global_groups_list() const;
void add_global_group(const StringName &p_name, const String &p_description);
@ -238,17 +218,10 @@ public:
String get_scene_groups_cache_path() const;
void load_scene_groups_cache();
// Testing a version allows fast cached GET_GLOBAL macros.
uint32_t get_version() const { return _version; }
#ifdef TOOLS_ENABLED
virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override;
#endif
void set_editor_setting_override(const String &p_setting, const Variant &p_value);
bool has_editor_setting_override(const String &p_setting) const;
Variant get_editor_setting_override(const String &p_setting) const;
ProjectSettings();
ProjectSettings(const String &p_path);
~ProjectSettings();
@ -270,26 +243,3 @@ Variant _GLOBAL_DEF(const PropertyInfo &p_info, const Variant &p_default, bool p
#define GLOBAL_DEF_RST_NOVAL_BASIC(m_var, m_value) _GLOBAL_DEF(m_var, m_value, true, true, true)
#define GLOBAL_DEF_INTERNAL(m_var, m_value) _GLOBAL_DEF(m_var, m_value, false, false, false, true)
/////////////////////////////////////////////////////////////////////////////////////////
// Cached versions of GLOBAL_GET.
// Cached but uses a typed variable for storage, this can be more efficient.
// Variables prefixed with _ggc_ to avoid shadowing warnings.
#define GLOBAL_GET_CACHED(m_type, m_setting_name) ([](const char *p_name) -> m_type {\
static_assert(std::is_trivially_destructible<m_type>::value, "GLOBAL_GET_CACHED must use a trivial type that allows static lifetime.");\
static m_type _ggc_local_var;\
static uint32_t _ggc_local_version = 0;\
static SpinLock _ggc_spin;\
uint32_t _ggc_new_version = ProjectSettings::get_singleton()->get_version();\
if (_ggc_local_version != _ggc_new_version) {\
_ggc_spin.lock();\
_ggc_local_version = _ggc_new_version;\
_ggc_local_var = ProjectSettings::get_singleton()->get_setting_with_override(p_name);\
m_type _ggc_temp = _ggc_local_var;\
_ggc_spin.unlock();\
return _ggc_temp;\
}\
_ggc_spin.lock();\
m_type _ggc_temp2 = _ggc_local_var;\
_ggc_spin.unlock();\
return _ggc_temp2; })(m_setting_name)

View file

@ -30,10 +30,6 @@
#ifndef DISABLE_DEPRECATED
#include "core_bind.h"
#include "core/object/class_db.h"
namespace CoreBind {
// Semaphore

View file

@ -31,20 +31,14 @@
#include "core_bind.h"
#include "core_bind.compat.inc"
#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/crypto/crypto_core.h"
#include "core/debugger/engine_debugger.h"
#include "core/debugger/script_debugger.h"
#include "core/io/file_access.h"
#include "core/io/marshalls.h"
#include "core/math/geometry_2d.h"
#include "core/math/geometry_3d.h"
#include "core/object/class_db.h"
#include "core/os/keyboard.h"
#include "core/os/main_loop.h"
#include "core/os/os.h"
#include "core/os/process_id.h"
#include "core/os/thread_safe.h"
#include "core/variant/typed_array.h"
@ -52,17 +46,17 @@ namespace CoreBind {
////// ResourceLoader //////
ResourceLoader *ResourceLoader::singleton = nullptr;
Error ResourceLoader::load_threaded_request(const String &p_path, const String &p_type_hint, bool p_use_sub_threads, CacheMode p_cache_mode) {
return ::ResourceLoader::load_threaded_request(p_path, p_type_hint, p_use_sub_threads, ResourceFormatLoader::CacheMode(p_cache_mode));
}
ResourceLoader::ThreadLoadStatus ResourceLoader::load_threaded_get_status(const String &p_path, Array r_progress) {
// Progress being the default array indicates the user hasn't requested for it to be computed.
// Default array should never be modified, it causes the hash of the method to change.
const bool return_progress = !ClassDB::is_default_array_arg(r_progress);
float progress = 0;
::ResourceLoader::ThreadLoadStatus tls = ::ResourceLoader::load_threaded_get_status(p_path, return_progress ? &progress : nullptr);
if (return_progress) {
::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;
}
@ -171,14 +165,10 @@ void ResourceLoader::_bind_methods() {
////// ResourceSaver //////
Error ResourceSaver::save(RequiredParam<Resource> p_resource, const String &p_path, BitField<SaverFlags> p_flags) {
Error ResourceSaver::save(const Ref<Resource> &p_resource, const String &p_path, BitField<SaverFlags> p_flags) {
return ::ResourceSaver::save(p_resource, p_path, p_flags);
}
Error ResourceSaver::set_uid(const String &p_path, ResourceUID::ID p_uid) {
return ::ResourceSaver::set_uid(p_path, p_uid);
}
Vector<String> ResourceSaver::get_recognized_extensions(const Ref<Resource> &p_resource) {
List<String> exts;
::ResourceSaver::get_recognized_extensions(p_resource, &exts);
@ -201,9 +191,10 @@ ResourceUID::ID ResourceSaver::get_resource_id_for_path(const String &p_path, bo
return ::ResourceSaver::get_resource_id_for_path(p_path, p_generate);
}
ResourceSaver *ResourceSaver::singleton = nullptr;
void ResourceSaver::_bind_methods() {
ClassDB::bind_method(D_METHOD("save", "resource", "path", "flags"), &ResourceSaver::save, DEFVAL(""), DEFVAL((uint32_t)FLAG_NONE));
ClassDB::bind_method(D_METHOD("set_uid", "resource", "uid"), &ResourceSaver::set_uid);
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);
@ -219,71 +210,8 @@ void ResourceSaver::_bind_methods() {
BIND_BITFIELD_FLAG(FLAG_REPLACE_SUBRESOURCE_PATHS);
}
////// Logger ///////
void Logger::_bind_methods() {
GDVIRTUAL_BIND(_log_error, "function", "file", "line", "code", "rationale", "editor_notify", "error_type", "script_backtraces");
GDVIRTUAL_BIND(_log_message, "message", "error");
BIND_ENUM_CONSTANT(ERROR_TYPE_ERROR);
BIND_ENUM_CONSTANT(ERROR_TYPE_WARNING);
BIND_ENUM_CONSTANT(ERROR_TYPE_SCRIPT);
BIND_ENUM_CONSTANT(ERROR_TYPE_SHADER);
}
void Logger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type, const TypedArray<ScriptBacktrace> &p_script_backtraces) {
GDVIRTUAL_CALL(_log_error, String::utf8(p_function), String::utf8(p_file), p_line, String::utf8(p_code), String::utf8(p_rationale), p_editor_notify, p_type, p_script_backtraces);
}
void Logger::log_message(const String &p_text, bool p_error) {
GDVIRTUAL_CALL(_log_message, p_text, p_error);
}
////// OS //////
void OS::LoggerBind::logv(const char *p_format, va_list p_list, bool p_err) {
if (!should_log(p_err)) {
return;
}
constexpr int static_buf_size = 1024;
char static_buf[static_buf_size] = { '\0' };
char *buf = static_buf;
va_list list_copy;
va_copy(list_copy, p_list);
int len = vsnprintf(buf, static_buf_size, p_format, p_list);
if (len >= static_buf_size) {
buf = (char *)Memory::alloc_static(len + 1);
vsnprintf(buf, len + 1, p_format, list_copy);
}
va_end(list_copy);
String str;
str.append_utf8(buf, len);
for (Ref<CoreBind::Logger> &logger : loggers) {
logger->log_message(str, p_err);
}
if (len >= static_buf_size) {
Memory::free_static(buf);
}
}
void OS::LoggerBind::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type, const Vector<Ref<ScriptBacktrace>> &p_script_backtraces) {
if (!should_log(true)) {
return;
}
TypedArray<ScriptBacktrace> backtraces;
backtraces.resize(p_script_backtraces.size());
for (int i = 0; i < p_script_backtraces.size(); i++) {
backtraces[i] = p_script_backtraces[i];
}
for (Ref<CoreBind::Logger> &logger : loggers) {
logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, CoreBind::Logger::ErrorType(p_type), backtraces);
}
}
PackedByteArray OS::get_entropy(int p_bytes) {
PackedByteArray pba;
pba.resize(p_bytes);
@ -429,7 +357,7 @@ int OS::create_instance(const Vector<String> &p_arguments) {
for (const String &arg : p_arguments) {
args.push_back(arg);
}
ProcessID pid = 0;
::OS::ProcessID pid = 0;
Error err = ::OS::get_singleton()->create_instance(args, &pid);
if (err != OK) {
return -1;
@ -437,20 +365,12 @@ int OS::create_instance(const Vector<String> &p_arguments) {
return pid;
}
Error OS::open_with_program(const String &p_program_path, const Vector<String> &p_paths) {
List<String> paths;
for (const String &path : p_paths) {
paths.push_back(path);
}
return ::OS::get_singleton()->open_with_program(p_program_path, paths);
}
int OS::create_process(const String &p_path, const Vector<String> &p_arguments, bool p_open_console) {
List<String> args;
for (const String &arg : p_arguments) {
args.push_back(arg);
}
ProcessID pid = 0;
::OS::ProcessID pid = 0;
Error err = ::OS::get_singleton()->create_process(p_path, args, &pid, p_open_console);
if (err != OK) {
return -1;
@ -669,7 +589,7 @@ bool OS::is_debug_build() const {
return true;
#else
return false;
#endif // DEBUG_ENABLED
#endif
}
String OS::get_system_dir(SystemDir p_dir, bool p_shared_storage) const {
@ -708,44 +628,7 @@ String OS::get_unique_id() const {
return ::OS::get_singleton()->get_unique_id();
}
void OS::add_logger(const Ref<Logger> &p_logger) {
ERR_FAIL_COND(p_logger.is_null());
if (!logger_bind) {
logger_bind = memnew(LoggerBind);
::OS::get_singleton()->add_logger(logger_bind);
}
ERR_FAIL_COND_MSG(logger_bind->loggers.find(p_logger) != -1, "Could not add logger, as it has already been added.");
logger_bind->loggers.push_back(p_logger);
}
void OS::remove_logger(const Ref<Logger> &p_logger) {
ERR_FAIL_COND(p_logger.is_null());
ERR_FAIL_COND_MSG(!logger_bind || logger_bind->loggers.find(p_logger) == -1, "Could not remove logger, as it hasn't been added.");
logger_bind->loggers.erase(p_logger);
}
void OS::remove_script_loggers(const ScriptLanguage *p_script) {
if (logger_bind) {
LocalVector<Ref<CoreBind::Logger>> to_remove;
for (const Ref<CoreBind::Logger> &logger : logger_bind->loggers) {
if (logger.is_null()) {
continue;
}
ScriptInstance *si = logger->get_script_instance();
if (!si) {
continue;
}
if (si->get_language() == p_script) {
to_remove.push_back(logger);
}
}
for (const Ref<CoreBind::Logger> &logger : to_remove) {
logger_bind->loggers.erase(logger);
}
}
}
OS *OS::singleton = nullptr;
void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_entropy", "size"), &OS::get_entropy);
@ -784,7 +667,6 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("execute_with_pipe", "path", "arguments", "blocking"), &OS::execute_with_pipe, DEFVAL(true));
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("open_with_program", "program_path", "paths"), &OS::open_with_program);
ClassDB::bind_method(D_METHOD("kill", "pid"), &OS::kill);
ClassDB::bind_method(D_METHOD("shell_open", "uri"), &OS::shell_open);
ClassDB::bind_method(D_METHOD("shell_show_in_file_manager", "file_or_dir_path", "open_folder"), &OS::shell_show_in_file_manager, DEFVAL(true));
@ -852,9 +734,6 @@ void OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_granted_permissions"), &OS::get_granted_permissions);
ClassDB::bind_method(D_METHOD("revoke_granted_permissions"), &OS::revoke_granted_permissions);
ClassDB::bind_method(D_METHOD("add_logger", "logger"), &OS::add_logger);
ClassDB::bind_method(D_METHOD("remove_logger", "logger"), &OS::remove_logger);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "low_processor_usage_mode"), "set_low_processor_usage_mode", "is_in_low_processor_usage_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "low_processor_usage_mode_sleep_usec"), "set_low_processor_usage_mode_sleep_usec", "get_low_processor_usage_mode_sleep_usec");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "delta_smoothing"), "set_delta_smoothing", "is_delta_smoothing_enabled");
@ -885,22 +764,10 @@ void OS::_bind_methods() {
BIND_ENUM_CONSTANT(STD_HANDLE_UNKNOWN);
}
OS::OS() {
singleton = this;
}
OS::~OS() {
if (singleton == this) {
singleton = nullptr;
}
if (logger_bind) {
logger_bind->clear();
}
}
////// Geometry2D //////
Geometry2D *Geometry2D::singleton = nullptr;
Geometry2D *Geometry2D::get_singleton() {
return singleton;
}
@ -1160,6 +1027,8 @@ void Geometry2D::_bind_methods() {
////// Geometry3D //////
Geometry3D *Geometry3D::singleton = nullptr;
Geometry3D *Geometry3D::get_singleton() {
return singleton;
}
@ -1302,6 +1171,8 @@ void Geometry3D::_bind_methods() {
////// Marshalls //////
Marshalls *Marshalls::singleton = nullptr;
Marshalls *Marshalls::get_singleton() {
return singleton;
}
@ -1534,10 +1405,6 @@ void Thread::set_thread_safety_checks_enabled(bool p_enabled) {
set_current_thread_safe_for_nodes(!p_enabled);
}
bool Thread::is_main_thread() {
return ::Thread::is_main_thread();
}
void Thread::_bind_methods() {
ClassDB::bind_method(D_METHOD("start", "callable", "priority"), &Thread::start, DEFVAL(PRIORITY_NORMAL));
ClassDB::bind_method(D_METHOD("get_id"), &Thread::get_id);
@ -1546,7 +1413,6 @@ void Thread::_bind_methods() {
ClassDB::bind_method(D_METHOD("wait_to_finish"), &Thread::wait_to_finish);
ClassDB::bind_static_method("Thread", D_METHOD("set_thread_safety_checks_enabled", "enabled"), &Thread::set_thread_safety_checks_enabled);
ClassDB::bind_static_method("Thread", D_METHOD("is_main_thread"), &Thread::is_main_thread);
BIND_ENUM_CONSTANT(PRIORITY_LOW);
BIND_ENUM_CONSTANT(PRIORITY_NORMAL);
@ -1558,16 +1424,14 @@ namespace Special {
////// ClassDB //////
PackedStringArray ClassDB::get_class_list() const {
LocalVector<StringName> classes;
::ClassDB::get_class_list(classes);
List<StringName> classes;
::ClassDB::get_class_list(&classes);
PackedStringArray ret;
ret.resize(classes.size());
String *ptrw = ret.ptrw();
int idx = 0;
for (const StringName &cls : classes) {
ptrw[idx] = cls;
idx++;
for (const StringName &E : classes) {
ret.set(idx++, E);
}
return ret;
@ -1705,8 +1569,14 @@ TypedArray<Dictionary> ClassDB::class_get_method_list(const StringName &p_class,
::ClassDB::get_method_list(p_class, &methods, p_no_inheritance);
TypedArray<Dictionary> ret;
for (const MethodInfo &method : methods) {
ret.push_back(method.operator Dictionary());
for (const MethodInfo &E : methods) {
#ifdef DEBUG_METHODS_ENABLED
ret.push_back(E.operator Dictionary());
#else
Dictionary dict;
dict["name"] = E.name;
ret.push_back(dict);
#endif
}
return ret;
@ -1815,12 +1685,8 @@ void ClassDB::get_argument_options(const StringName &p_function, int p_idx, List
pf == "is_class_enabled" || pf == "is_class_enum_bitfield" || pf == "class_get_api_type");
}
if (first_argument_is_class || pf == "is_parent_class") {
LocalVector<StringName> classes;
::ClassDB::get_class_list(classes);
for (const StringName &E : classes) {
if (::ClassDB::is_class_exposed(E)) {
r_options->push_back(E.operator String().quote());
}
for (const String &E : get_class_list()) {
r_options->push_back(E.quote());
}
}
@ -2032,16 +1898,6 @@ ScriptLanguage *Engine::get_script_language(int p_index) const {
return ScriptServer::get_language(p_index);
}
TypedArray<ScriptBacktrace> Engine::capture_script_backtraces(bool p_include_variables) const {
Vector<Ref<ScriptBacktrace>> backtraces = ScriptServer::capture_script_backtraces(p_include_variables);
TypedArray<ScriptBacktrace> result;
result.resize(backtraces.size());
for (int i = 0; i < backtraces.size(); i++) {
result[i] = backtraces[i];
}
return result;
}
void Engine::set_editor_hint(bool p_enabled) {
::Engine::get_singleton()->set_editor_hint(p_enabled);
}
@ -2129,7 +1985,6 @@ void Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("unregister_script_language", "language"), &Engine::unregister_script_language);
ClassDB::bind_method(D_METHOD("get_script_language_count"), &Engine::get_script_language_count);
ClassDB::bind_method(D_METHOD("get_script_language", "index"), &Engine::get_script_language);
ClassDB::bind_method(D_METHOD("capture_script_backtraces", "include_variables"), &Engine::capture_script_backtraces, DEFVAL(false));
ClassDB::bind_method(D_METHOD("is_editor_hint"), &Engine::is_editor_hint);
ClassDB::bind_method(D_METHOD("is_embedded_in_editor"), &Engine::is_embedded_in_editor);
@ -2151,6 +2006,8 @@ void Engine::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "physics_jitter_fix"), "set_physics_jitter_fix", "get_physics_jitter_fix");
}
Engine *Engine::singleton = nullptr;
////// EngineDebugger //////
bool EngineDebugger::is_active() {
@ -2296,6 +2153,8 @@ EngineDebugger::~EngineDebugger() {
captures.clear();
}
EngineDebugger *EngineDebugger::singleton = nullptr;
void EngineDebugger::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_active"), &EngineDebugger::is_active);

View file

@ -31,17 +31,15 @@
#pragma once
#include "core/debugger/engine_profiler.h"
#include "core/io/logger.h"
#include "core/io/resource_loader.h"
#include "core/io/resource_saver.h"
#include "core/object/class_db.h"
#include "core/object/script_backtrace.h"
#include "core/os/semaphore.h"
#include "core/os/thread.h"
#include "core/templates/safe_refcount.h"
#include "core/variant/typed_array.h"
class MainLoop;
template <typename T>
class TypedArray;
namespace CoreBind {
@ -50,7 +48,7 @@ class ResourceLoader : public Object {
protected:
static void _bind_methods();
static inline ResourceLoader *singleton = nullptr;
static ResourceLoader *singleton;
public:
enum ThreadLoadStatus {
@ -95,7 +93,7 @@ class ResourceSaver : public Object {
protected:
static void _bind_methods();
static inline ResourceSaver *singleton = nullptr;
static ResourceSaver *singleton;
public:
enum SaverFlags {
@ -111,8 +109,7 @@ public:
static ResourceSaver *get_singleton() { return singleton; }
Error save(RequiredParam<Resource> p_resource, const String &p_path, BitField<SaverFlags> p_flags);
Error set_uid(const String &p_path, ResourceUID::ID p_uid);
Error save(const Ref<Resource> &p_resource, const String &p_path, BitField<SaverFlags> p_flags);
Vector<String> get_recognized_extensions(const Ref<Resource> &p_resource);
void add_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver, bool p_at_front);
void remove_resource_format_saver(Ref<ResourceFormatSaver> p_format_saver);
@ -122,47 +119,14 @@ public:
ResourceSaver() { singleton = this; }
};
class Logger : public RefCounted {
GDCLASS(Logger, RefCounted);
public:
enum ErrorType {
ERROR_TYPE_ERROR,
ERROR_TYPE_WARNING,
ERROR_TYPE_SCRIPT,
ERROR_TYPE_SHADER,
};
protected:
GDVIRTUAL2(_log_message, String, bool);
GDVIRTUAL8(_log_error, String, String, int, String, String, bool, int, TypedArray<ScriptBacktrace>);
static void _bind_methods();
public:
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERROR_TYPE_ERROR, const TypedArray<ScriptBacktrace> &p_script_backtraces = {});
virtual void log_message(const String &p_text, bool p_error);
};
class OS : public Object {
GDCLASS(OS, Object);
mutable HashMap<String, bool> feature_cache;
class LoggerBind : public ::Logger {
public:
LocalVector<Ref<CoreBind::Logger>> loggers;
virtual void logv(const char *p_format, va_list p_list, bool p_err) override _PRINTF_FORMAT_ATTRIBUTE_2_0;
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR, const Vector<Ref<ScriptBacktrace>> &p_script_backtraces = {}) override;
void clear() { loggers.clear(); }
};
LoggerBind *logger_bind = nullptr;
protected:
static void _bind_methods();
static inline OS *singleton = nullptr;
static OS *singleton;
#ifndef DISABLE_DEPRECATED
Dictionary _execute_with_pipe_bind_compat_94434(const String &p_path, const Vector<String> &p_arguments);
@ -221,7 +185,6 @@ public:
Dictionary execute_with_pipe(const String &p_path, const Vector<String> &p_arguments, bool p_blocking = true);
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 open_with_program(const String &p_program_path, const Vector<String> &p_paths);
Error kill(int p_pid);
Error shell_open(const String &p_uri);
Error shell_show_in_file_manager(const String &p_path, bool p_open_folder = true);
@ -311,20 +274,15 @@ public:
Vector<String> get_granted_permissions() const;
void revoke_granted_permissions();
void add_logger(const Ref<Logger> &p_logger);
void remove_logger(const Ref<Logger> &p_logger);
void remove_script_loggers(const ScriptLanguage *p_script);
static OS *get_singleton() { return singleton; }
OS();
~OS();
OS() { singleton = this; }
};
class Geometry2D : public Object {
GDCLASS(Geometry2D, Object);
static inline Geometry2D *singleton = nullptr;
static Geometry2D *singleton;
protected:
static void _bind_methods();
@ -390,7 +348,7 @@ public:
class Geometry3D : public Object {
GDCLASS(Geometry3D, Object);
static inline Geometry3D *singleton = nullptr;
static Geometry3D *singleton;
protected:
static void _bind_methods();
@ -421,7 +379,7 @@ public:
class Marshalls : public Object {
GDCLASS(Marshalls, Object);
static inline Marshalls *singleton = nullptr;
static Marshalls *singleton;
protected:
static void _bind_methods();
@ -497,7 +455,6 @@ public:
Variant wait_to_finish();
static void set_thread_safety_checks_enabled(bool p_enabled);
static bool is_main_thread();
};
namespace Special {
@ -561,6 +518,9 @@ public:
#ifdef TOOLS_ENABLED
virtual void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const override;
#endif
ClassDB() {}
~ClassDB() {}
};
} // namespace Special
@ -570,7 +530,7 @@ class Engine : public Object {
protected:
static void _bind_methods();
static inline Engine *singleton = nullptr;
static Engine *singleton;
public:
static Engine *get_singleton() { return singleton; }
@ -619,7 +579,6 @@ public:
Error unregister_script_language(const ScriptLanguage *p_language);
int get_script_language_count();
ScriptLanguage *get_script_language(int p_index) const;
TypedArray<ScriptBacktrace> capture_script_backtraces(bool p_include_variables = false) const;
void set_editor_hint(bool p_enabled);
bool is_editor_hint() const;
@ -650,7 +609,7 @@ class EngineDebugger : public Object {
protected:
static void _bind_methods();
static inline EngineDebugger *singleton = nullptr;
static EngineDebugger *singleton;
public:
static EngineDebugger *get_singleton() { return singleton; }
@ -694,7 +653,6 @@ public:
} // namespace CoreBind
VARIANT_ENUM_CAST(CoreBind::Logger::ErrorType);
VARIANT_ENUM_CAST(CoreBind::ResourceLoader::ThreadLoadStatus);
VARIANT_ENUM_CAST(CoreBind::ResourceLoader::CacheMode);

View file

@ -6,71 +6,6 @@ from io import TextIOWrapper
import methods
# Generate disabled classes
def disabled_class_builder(target, source, env):
with methods.generated_wrapper(str(target[0])) as file:
for c in source[0].read():
if cs := c.strip():
file.write(f"class {cs}; template <> struct is_class_enabled<{cs}> : std::false_type {{}};\n")
# Generate version info
def version_info_builder(target, source, env):
with methods.generated_wrapper(str(target[0])) as file:
file.write(
"""\
#define GODOT_VERSION_SHORT_NAME "{short_name}"
#define GODOT_VERSION_NAME "{name}"
#define GODOT_VERSION_MAJOR {major}
#define GODOT_VERSION_MINOR {minor}
#define GODOT_VERSION_PATCH {patch}
#define GODOT_VERSION_STATUS "{status}"
#define GODOT_VERSION_BUILD "{build}"
#define GODOT_VERSION_MODULE_CONFIG "{module_config}"
#define GODOT_VERSION_WEBSITE "{website}"
#define GODOT_VERSION_DOCS_BRANCH "{docs_branch}"
#define GODOT_VERSION_DOCS_URL "https://docs.godotengine.org/en/" GODOT_VERSION_DOCS_BRANCH
""".format(**source[0].read())
)
def version_hash_builder(target, source, env):
with methods.generated_wrapper(str(target[0])) as file:
file.write(
"""\
#include "core/version.h"
const char *const GODOT_VERSION_HASH = "{git_hash}";
const unsigned long long GODOT_VERSION_TIMESTAMP = {git_timestamp};
""".format(**source[0].read())
)
def encryption_key_builder(target, source, env):
src = source[0].read() or "0" * 64
try:
buffer = bytes.fromhex(src)
if len(buffer) != 32:
raise ValueError
except ValueError:
methods.print_error(
f'Invalid AES256 encryption key, not 64 hexadecimal characters: "{src}".\n'
"Unset `SCRIPT_AES256_ENCRYPTION_KEY` in your environment "
"or make sure that it contains exactly 64 hexadecimal characters."
)
raise
with methods.generated_wrapper(str(target[0])) as file:
file.write(
f"""\
#include <cstdint>
uint8_t script_encryption_key[32] = {{
{methods.format_buffer(buffer, 1)}
}};"""
)
def make_certs_header(target, source, env):
buffer = methods.get_buffer(str(source[0]))
decomp_size = len(buffer)
@ -78,8 +13,8 @@ def make_certs_header(target, source, env):
with methods.generated_wrapper(str(target[0])) as file:
# System certs path. Editor will use them if defined. (for package maintainers)
file.write('#define _SYSTEM_CERTS_PATH "{}"\n'.format(source[2].read() or ""))
if source[1].read():
file.write('#define _SYSTEM_CERTS_PATH "{}"\n'.format(env["system_certs_path"]))
if env["builtin_certs"]:
# Defined here and not in env so changing it does not trigger a full rebuild.
file.write(f"""\
#define BUILTIN_CERTS_ENABLED

View file

@ -30,26 +30,23 @@
#include "core_constants.h"
#include "core/input/input_enums.h"
#include "core/object/method_bind.h" // IWYU pragma: keep. To bind `MethodFlags`.
#include "core/object/object.h"
#include "core/input/input_event.h"
#include "core/object/class_db.h"
#include "core/os/keyboard.h"
#include "core/variant/type_info.h"
#include "core/variant/variant.h"
#include "core/variant/variant_caster.h"
struct _CoreConstant {
#ifdef DEBUG_ENABLED
#ifdef DEBUG_METHODS_ENABLED
bool ignore_value_in_docs = false;
bool is_bitfield = false;
#endif // DEBUG_ENABLED
#endif
StringName enum_name;
const char *name = nullptr;
int64_t value = 0;
_CoreConstant() {}
#ifdef DEBUG_ENABLED
#ifdef DEBUG_METHODS_ENABLED
_CoreConstant(const StringName &p_enum_name, const char *p_name, int64_t p_value, bool p_ignore_value_in_docs = false, bool p_is_bitfield = false) :
ignore_value_in_docs(p_ignore_value_in_docs),
is_bitfield(p_is_bitfield),
@ -63,14 +60,14 @@ struct _CoreConstant {
name(p_name),
value(p_value) {
}
#endif // DEBUG_ENABLED
#endif
};
static Vector<_CoreConstant> _global_constants;
static HashMap<StringName, int> _global_constants_map;
static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#ifdef DEBUG_ENABLED
#ifdef DEBUG_METHODS_ENABLED
#define BIND_CORE_CONSTANT(m_constant) \
_global_constants.push_back(_CoreConstant(StringName(), #m_constant, m_constant)); \
@ -78,7 +75,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -86,7 +83,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_constant); \
StringName enum_name = __constant_get_bitfield_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, false, true)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -95,7 +92,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
// This just binds enum classes as if they were regular enum constants.
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -103,7 +100,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_prefix "_" #m_member); \
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member, false, true)); \
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -111,7 +108,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_name); \
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -119,7 +116,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_name); \
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member, false, true)); \
_global_constants_map[#m_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -127,7 +124,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member, true)); \
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -135,7 +132,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -147,7 +144,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant, true)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -155,7 +152,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant, true)); \
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -169,7 +166,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -177,7 +174,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_BITFIELD_FLAG(m_constant) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_constant); \
StringName enum_name = __constant_get_bitfield_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -186,7 +183,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
// This just binds enum classes as if they were regular enum constants.
#define BIND_CORE_ENUM_CLASS_CONSTANT(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -194,7 +191,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_BITFIELD_CLASS_FLAG(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_prefix "_" #m_member); \
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -202,7 +199,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CLASS_CONSTANT_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_name); \
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -210,7 +207,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_BITFIELD_CLASS_FLAG_CUSTOM(m_enum, m_name, m_member) \
{ \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member); \
StringName enum_name = __constant_get_bitfield_name(m_enum::m_member, #m_name); \
_global_constants.push_back(_CoreConstant(enum_name, #m_name, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -218,7 +215,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CLASS_CONSTANT_NO_VAL(m_enum, m_prefix, m_member) \
{ \
StringName enum_name = __constant_get_enum_name(m_enum::m_member); \
StringName enum_name = __constant_get_enum_name(m_enum::m_member, #m_prefix "_" #m_member); \
_global_constants.push_back(_CoreConstant(enum_name, #m_prefix "_" #m_member, (int64_t)m_enum::m_member)); \
_global_constants_map[#m_prefix "_" #m_member] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -226,7 +223,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT_CUSTOM(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -238,7 +235,7 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT_NO_VAL(m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, #m_constant, m_constant)); \
_global_constants_map[#m_constant] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
@ -246,13 +243,13 @@ static HashMap<StringName, Vector<_CoreConstant>> _global_enums;
#define BIND_CORE_ENUM_CONSTANT_CUSTOM_NO_VAL(m_custom_name, m_constant) \
{ \
StringName enum_name = __constant_get_enum_name(m_constant); \
StringName enum_name = __constant_get_enum_name(m_constant, #m_constant); \
_global_constants.push_back(_CoreConstant(enum_name, m_custom_name, m_constant)); \
_global_constants_map[m_custom_name] = _global_constants.size() - 1; \
_global_enums[enum_name].push_back((_global_constants.ptr())[_global_constants.size() - 1]); \
}
#endif // DEBUG_ENABLED
#endif
void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(SIDE_LEFT);
@ -552,11 +549,6 @@ void register_global_constants() {
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE3);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, PADDLE4);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, TOUCHPAD);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MISC2);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MISC3);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MISC4);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MISC5);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MISC6);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, SDL_MAX);
BIND_CORE_ENUM_CLASS_CONSTANT(JoyButton, JOY_BUTTON, MAX);
@ -686,9 +678,6 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PASSWORD);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_TOOL_BUTTON);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ONESHOT);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_GROUP_ENABLE);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INPUT_NAME);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_FILE_PATH);
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX);
BIND_CORE_BITFIELD_FLAG(PROPERTY_USAGE_NONE);
@ -737,18 +726,6 @@ void register_global_constants() {
BIND_CORE_BITFIELD_FLAG(METHOD_FLAG_VIRTUAL_REQUIRED);
BIND_CORE_BITFIELD_FLAG(METHOD_FLAGS_DEFAULT);
BIND_CORE_CONSTANT(UINT8_MAX);
BIND_CORE_CONSTANT(UINT16_MAX);
BIND_CORE_CONSTANT(UINT32_MAX);
BIND_CORE_CONSTANT(INT8_MIN);
BIND_CORE_CONSTANT(INT8_MAX);
BIND_CORE_CONSTANT(INT16_MIN);
BIND_CORE_CONSTANT(INT16_MAX);
BIND_CORE_CONSTANT(INT32_MIN);
BIND_CORE_CONSTANT(INT32_MAX);
BIND_CORE_CONSTANT(INT64_MIN);
BIND_CORE_CONSTANT(INT64_MAX);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_NIL", Variant::NIL);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_BOOL", Variant::BOOL);
BIND_CORE_ENUM_CONSTANT_CUSTOM("TYPE_INT", Variant::INT);
@ -837,7 +814,7 @@ StringName CoreConstants::get_global_constant_enum(int p_idx) {
return _global_constants[p_idx].enum_name;
}
#ifdef DEBUG_ENABLED
#ifdef DEBUG_METHODS_ENABLED
bool CoreConstants::is_global_constant_bitfield(int p_idx) {
return _global_constants[p_idx].is_bitfield;
}
@ -853,7 +830,7 @@ bool CoreConstants::is_global_constant_bitfield(int p_idx) {
bool CoreConstants::get_ignore_value_in_docs(int p_idx) {
return false;
}
#endif // DEBUG_ENABLED
#endif
const char *CoreConstants::get_global_constant_name(int p_idx) {
return _global_constants[p_idx].name;
@ -883,13 +860,3 @@ void CoreConstants::get_enum_values(const StringName &p_enum, HashMap<StringName
(*p_values)[constant.name] = constant.value;
}
}
#ifdef TOOLS_ENABLED
void CoreConstants::get_global_enums(List<StringName> *r_values) {
for (const KeyValue<StringName, Vector<_CoreConstant>> &global_enum : _global_enums) {
r_values->push_back(global_enum.key);
}
}
#endif

View file

@ -32,7 +32,6 @@
#include "core/string/string_name.h"
#include "core/templates/hash_map.h"
#include "core/templates/list.h"
class CoreConstants {
public:
@ -45,8 +44,5 @@ public:
static bool is_global_constant(const StringName &p_name);
static int get_global_constant_index(const StringName &p_name);
static bool is_global_enum(const StringName &p_enum);
static void get_enum_values(const StringName &p_enum, HashMap<StringName, int64_t> *r_values);
#ifdef TOOLS_ENABLED
static void get_global_enums(List<StringName> *r_values);
#endif
static void get_enum_values(const StringName &p_enum, HashMap<StringName, int64_t> *p_values);
};

View file

@ -1,5 +1,5 @@
/**************************************************************************/
/* bridging_header_apple_embedded.h */
/* core_globals.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,9 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core_globals.h"
#import "app_delegate_service.h"
#import "godot_app_delegate.h"
#import "godot_view_apple_embedded.h"
#import "godot_view_controller.h"
bool CoreGlobals::leak_reporting_enabled = true;
bool CoreGlobals::print_line_enabled = true;
bool CoreGlobals::print_error_enabled = true;

View file

@ -35,7 +35,7 @@
class CoreGlobals {
public:
static inline bool leak_reporting_enabled = true;
static inline bool print_line_enabled = true;
static inline bool print_error_enabled = true;
static bool leak_reporting_enabled;
static bool print_line_enabled;
static bool print_error_enabled;
};

View file

@ -44,45 +44,45 @@ public:
_FORCE_INLINE_ static CoreStringNames *get_singleton() { return singleton; }
const StringName free_ = "free"; // free would conflict with C++ keyword.
const StringName changed = "changed";
const StringName script = "script";
const StringName script_changed = "script_changed";
const StringName _iter_init = "_iter_init";
const StringName _iter_next = "_iter_next";
const StringName _iter_get = "_iter_get";
const StringName get_rid = "get_rid";
const StringName _to_string = "_to_string";
const StringName _custom_features = "_custom_features";
const StringName free_ = StaticCString::create("free"); // free would conflict with C++ keyword.
const StringName changed = StaticCString::create("changed");
const StringName script = StaticCString::create("script");
const StringName script_changed = StaticCString::create("script_changed");
const StringName _iter_init = StaticCString::create("_iter_init");
const StringName _iter_next = StaticCString::create("_iter_next");
const StringName _iter_get = StaticCString::create("_iter_get");
const StringName get_rid = StaticCString::create("get_rid");
const StringName _to_string = StaticCString::create("_to_string");
const StringName _custom_features = StaticCString::create("_custom_features");
const StringName x = "x";
const StringName y = "y";
const StringName z = "z";
const StringName w = "w";
const StringName r = "r";
const StringName g = "g";
const StringName b = "b";
const StringName a = "a";
const StringName position = "position";
const StringName size = "size";
const StringName end = "end";
const StringName basis = "basis";
const StringName origin = "origin";
const StringName normal = "normal";
const StringName d = "d";
const StringName h = "h";
const StringName s = "s";
const StringName v = "v";
const StringName r8 = "r8";
const StringName g8 = "g8";
const StringName b8 = "b8";
const StringName a8 = "a8";
const StringName x = StaticCString::create("x");
const StringName y = StaticCString::create("y");
const StringName z = StaticCString::create("z");
const StringName w = StaticCString::create("w");
const StringName r = StaticCString::create("r");
const StringName g = StaticCString::create("g");
const StringName b = StaticCString::create("b");
const StringName a = StaticCString::create("a");
const StringName position = StaticCString::create("position");
const StringName size = StaticCString::create("size");
const StringName end = StaticCString::create("end");
const StringName basis = StaticCString::create("basis");
const StringName origin = StaticCString::create("origin");
const StringName normal = StaticCString::create("normal");
const StringName d = StaticCString::create("d");
const StringName h = StaticCString::create("h");
const StringName s = StaticCString::create("s");
const StringName v = StaticCString::create("v");
const StringName r8 = StaticCString::create("r8");
const StringName g8 = StaticCString::create("g8");
const StringName b8 = StaticCString::create("b8");
const StringName a8 = StaticCString::create("a8");
const StringName call = "call";
const StringName call_deferred = "call_deferred";
const StringName bind = "bind";
const StringName notification = "notification";
const StringName property_list_changed = "property_list_changed";
const StringName call = StaticCString::create("call");
const StringName call_deferred = StaticCString::create("call_deferred");
const StringName bind = StaticCString::create("bind");
const StringName notification = StaticCString::create("notification");
const StringName property_list_changed = StaticCString::create("property_list_changed");
};
#define CoreStringName(m_name) CoreStringNames::get_singleton()->m_name

View file

@ -13,7 +13,7 @@ if is_builtin or not has_module:
# Use our headers for builtin or if the module is not going to be compiled.
# We decided not to depend on system mbedtls just for these few files that can
# be easily extracted.
env_crypto.Prepend(CPPPATH=["#thirdparty/mbedtls/include"])
env_crypto.Prepend(CPPEXTPATH=["#thirdparty/mbedtls/include"])
# MbedTLS core functions (for CryptoCore).
# If the mbedtls module is compiled we don't need to add the .c files with our

View file

@ -28,9 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "aes_context.h"
#include "core/object/class_db.h"
#include "core/crypto/aes_context.h"
Error AESContext::start(Mode p_mode, const PackedByteArray &p_key, const PackedByteArray &p_iv) {
ERR_FAIL_COND_V_MSG(mode != MODE_MAX, ERR_ALREADY_IN_USE, "AESContext already started. Call 'finish' before starting a new one.");
@ -112,3 +110,6 @@ void AESContext::_bind_methods() {
BIND_ENUM_CONSTANT(MODE_CBC_DECRYPT);
BIND_ENUM_CONSTANT(MODE_MAX);
}
AESContext::AESContext() {
}

View file

@ -32,7 +32,6 @@
#include "core/crypto/crypto_core.h"
#include "core/object/ref_counted.h"
#include "core/variant/type_info.h"
class AESContext : public RefCounted {
GDCLASS(AESContext, RefCounted);
@ -59,6 +58,8 @@ public:
PackedByteArray update(const PackedByteArray &p_src);
PackedByteArray get_iv_state();
void finish();
AESContext();
};
VARIANT_ENUM_CAST(AESContext::Mode);

View file

@ -30,8 +30,6 @@
#include "crypto.h"
#include "core/object/class_db.h"
/// Resources
CryptoKey *(*CryptoKey::_create)(bool p_notify_postinitialize) = nullptr;
@ -233,7 +231,8 @@ Error ResourceFormatSaverCrypto::save(const Ref<Resource> &p_resource, const Str
if (cert.is_valid()) {
err = cert->save(p_path);
} else if (key.is_valid()) {
err = key->save(p_path, p_path.has_extension("pub"));
String el = p_path.get_extension().to_lower();
err = key->save(p_path, el == "pub");
} else {
ERR_FAIL_V(ERR_INVALID_PARAMETER);
}

View file

@ -114,6 +114,7 @@ public:
virtual Error update(const PackedByteArray &p_data) = 0;
virtual PackedByteArray finish() = 0;
HMACContext() {}
virtual ~HMACContext() {}
};
@ -143,11 +144,11 @@ public:
// Compares two PackedByteArrays for equality without leaking timing information in order to prevent timing attacks.
// @see: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy
bool constant_time_compare(const PackedByteArray &p_trusted, const PackedByteArray &p_received);
Crypto() {}
};
class ResourceFormatLoaderCrypto : public ResourceFormatLoader {
GDSOFTCLASS(ResourceFormatLoaderCrypto, ResourceFormatLoader);
public:
virtual Ref<Resource> load(const String &p_path, const String &p_original_path = "", Error *r_error = nullptr, bool p_use_sub_threads = false, float *r_progress = nullptr, CacheMode p_cache_mode = CACHE_MODE_REUSE) override;
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
@ -160,8 +161,6 @@ public:
};
class ResourceFormatSaverCrypto : public ResourceFormatSaver {
GDSOFTCLASS(ResourceFormatSaverCrypto, ResourceFormatSaver);
public:
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0) override;
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const override;

View file

@ -31,7 +31,6 @@
#include "crypto_core.h"
#include "core/os/os.h"
#include "core/string/ustring.h"
#include <mbedtls/aes.h>
#include <mbedtls/base64.h>

View file

@ -30,12 +30,7 @@
#pragma once
#include "core/error/error_list.h"
#include <cstddef>
#include <cstdint>
class String;
#include "core/object/ref_counted.h"
class CryptoCore {
public:

View file

@ -31,7 +31,6 @@
#include "hashing_context.h"
#include "core/crypto/crypto_core.h"
#include "core/object/class_db.h"
Error HashingContext::start(HashType p_type) {
ERR_FAIL_COND_V(ctx != nullptr, ERR_ALREADY_IN_USE);

View file

@ -31,7 +31,6 @@
#pragma once
#include "core/object/ref_counted.h"
#include "core/variant/type_info.h"
class HashingContext : public RefCounted {
GDCLASS(HashingContext, RefCounted);
@ -57,6 +56,7 @@ public:
Error update(const PackedByteArray &p_chunk);
PackedByteArray finish();
HashingContext() {}
~HashingContext();
};

View file

@ -46,6 +46,7 @@ struct DebuggerMarshalls {
struct ScriptStackDump {
List<ScriptLanguage::StackInfo> frames;
ScriptStackDump() {}
Array serialize();
bool deserialize(const Array &p_arr);

View file

@ -36,6 +36,13 @@
#include "core/debugger/script_debugger.h"
#include "core/os/os.h"
EngineDebugger *EngineDebugger::singleton = nullptr;
ScriptDebugger *EngineDebugger::script_debugger = nullptr;
HashMap<StringName, EngineDebugger::Profiler> EngineDebugger::profilers;
HashMap<StringName, EngineDebugger::Capture> EngineDebugger::captures;
HashMap<String, EngineDebugger::CreatePeerFunc> EngineDebugger::protocols;
void (*EngineDebugger::allow_focus_steal_fn)();
void EngineDebugger::register_profiler(const StringName &p_name, const Profiler &p_func) {
@ -121,10 +128,7 @@ void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_process_ticks,
}
void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, bool p_ignore_error_breaks, const Vector<String> &p_breakpoints, void (*p_allow_focus_steal_fn)()) {
register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create_tcp); // TCP is the default protocol. Platforms/modules can add more.
#ifdef UNIX_ENABLED
register_uri_handler("unix://", RemoteDebuggerPeerTCP::create_unix);
#endif
register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create); // TCP is the default protocol. Platforms/modules can add more.
if (p_uri.is_empty()) {
return;
}
@ -135,10 +139,10 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, bo
OS::get_singleton()->initialize_debugging();
} else if (p_uri.contains("://")) {
const String proto = p_uri.substr(0, p_uri.find("://") + 3);
CreatePeerFunc *create_fn = protocols.getptr(proto);
ERR_FAIL_NULL_MSG(create_fn, vformat("Invalid protocol: %s.", proto));
RemoteDebuggerPeer *peer = (*create_fn)(p_uri);
if (!protocols.has(proto)) {
return;
}
RemoteDebuggerPeer *peer = protocols[proto](p_uri);
if (!peer) {
return;
}

View file

@ -91,12 +91,12 @@ private:
uint32_t poll_every = 0;
protected:
static inline EngineDebugger *singleton = nullptr;
static inline ScriptDebugger *script_debugger = nullptr;
static EngineDebugger *singleton;
static ScriptDebugger *script_debugger;
static inline HashMap<StringName, Profiler> profilers;
static inline HashMap<StringName, Capture> captures;
static inline HashMap<String, CreatePeerFunc> protocols;
static HashMap<StringName, Profiler> profilers;
static HashMap<StringName, Capture> captures;
static HashMap<String, CreatePeerFunc> protocols;
static void (*allow_focus_steal_fn)();

View file

@ -31,7 +31,6 @@
#include "engine_profiler.h"
#include "core/debugger/engine_debugger.h"
#include "core/object/class_db.h" // IWYU pragma: keep. `GDVIRTUAL_BIND` macro.
void EngineProfiler::_bind_methods() {
GDVIRTUAL_BIND(_toggle, "enable", "options");

View file

@ -30,7 +30,7 @@
#pragma once
#include "core/object/gdvirtual.gen.h"
#include "core/object/gdvirtual.gen.inc"
#include "core/object/ref_counted.h"
class EngineProfiler : public RefCounted {
@ -55,5 +55,6 @@ public:
GDVIRTUAL1(_add_frame, Array);
GDVIRTUAL4(_tick, double, double, double, double);
EngineProfiler() {}
virtual ~EngineProfiler();
};

View file

@ -31,11 +31,8 @@
#include "local_debugger.h"
#include "core/debugger/script_debugger.h"
#include "core/os/main_loop.h"
#include "core/os/os.h"
#include <cstdio>
struct LocalDebugger::ScriptsProfiler {
struct ProfileInfoSort {
bool operator()(const ScriptLanguage::ProfilingInfo &A, const ScriptLanguage::ProfilingInfo &B) const {
@ -117,10 +114,6 @@ struct LocalDebugger::ScriptsProfiler {
};
void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
if (script_debugger->is_ignoring_error_breaks() && p_is_error_breakpoint) {
return;
}
ScriptLanguage *script_lang = script_debugger->get_break_language();
if (!target_function.is_empty()) {
@ -231,10 +224,6 @@ void LocalDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
script_debugger->set_depth(0);
script_debugger->set_lines_left(1);
break;
} else if (line == "o" || line == "out") {
script_debugger->set_depth(1);
script_debugger->set_lines_left(1);
break;
} else if (line == "fin" || line == "finish") {
String current_function = script_lang->debug_get_stack_level_function(0);
@ -373,7 +362,7 @@ void LocalDebugger::send_message(const String &p_message, const Array &p_args) {
}
void LocalDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) {
_err_print_error(p_func.utf8().get_data(), p_file.utf8().get_data(), p_line, p_err, p_descr, p_editor_notify, p_type);
print_line("ERROR: '" + (p_descr.is_empty() ? p_err : p_descr) + "'");
}
LocalDebugger::LocalDebugger() {

View file

@ -31,6 +31,7 @@
#pragma once
#include "core/debugger/engine_debugger.h"
#include "core/object/script_language.h"
#include "core/templates/list.h"
class LocalDebugger : public EngineDebugger {

View file

@ -30,7 +30,6 @@
#include "remote_debugger.h"
#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/debugger/debugger_marshalls.h"
#include "core/debugger/engine_debugger.h"
@ -39,10 +38,9 @@
#include "core/input/input.h"
#include "core/io/resource_loader.h"
#include "core/math/expression.h"
#include "core/object/class_db.h"
#include "core/object/script_language.h"
#include "core/os/os.h"
#include "servers/display/display_server.h"
#include "servers/display_server.h"
class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
Object *performance = nullptr;
@ -50,9 +48,9 @@ class RemoteDebugger::PerformanceProfiler : public EngineProfiler {
uint64_t last_monitor_modification_time = 0;
public:
void toggle(bool p_enable, const Array &p_opts) override {}
void add(const Array &p_data) override {}
void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) override {
void toggle(bool p_enable, const Array &p_opts) {}
void add(const Array &p_data) {}
void tick(double p_frame_time, double p_process_time, double p_physics_time, double p_physics_frame_time) {
if (!performance) {
return;
}
@ -64,16 +62,11 @@ public:
last_perf_time = pt;
Array custom_monitor_names = performance->call("get_custom_monitor_names");
Array custom_monitor_types = performance->call("get_custom_monitor_types");
Array custom_monitor_data;
custom_monitor_data.push_back(custom_monitor_names);
custom_monitor_data.push_back(custom_monitor_types);
uint64_t monitor_modification_time = performance->call("get_monitor_modification_time");
if (monitor_modification_time > last_monitor_modification_time) {
last_monitor_modification_time = monitor_modification_time;
EngineDebugger::get_singleton()->send_message("performance:profile_names", custom_monitor_data);
EngineDebugger::get_singleton()->send_message("performance:profile_names", custom_monitor_names);
}
int max = performance->get("MONITOR_MAX");
@ -111,6 +104,10 @@ Error RemoteDebugger::_put_msg(const String &p_message, const Array &p_data) {
}
void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, bool p_editor_notify, ErrorHandlerType p_type) {
if (p_type == ERR_HANDLER_SCRIPT) {
return; //ignore script errors, those go through debugger
}
RemoteDebugger *rd = static_cast<RemoteDebugger *>(p_this);
if (rd->flushing && Thread::get_caller_id() == rd->flush_thread) { // Can't handle recursive errors during flush.
return;
@ -403,37 +400,40 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
return;
}
if (script_debugger->is_ignoring_error_breaks() && p_is_error_breakpoint) {
return;
}
ERR_FAIL_COND_MSG(!is_peer_connected(), "Script Debugger failed to connect, but being used anyway.");
if (!peer->can_block()) {
return; // Peer does not support blocking IO. We could at least send the error though.
}
threads_in_break.insert(Thread::get_caller_id());
}
ScriptLanguage *script_lang = script_debugger->get_break_language();
ERR_FAIL_NULL(script_lang);
const bool can_break = !(p_is_error_breakpoint && script_debugger->is_ignoring_error_breaks());
const String error_str = script_lang ? script_lang->debug_get_error() : "";
if (can_break) {
Array msg = {
p_can_continue,
script_lang ? script_lang->debug_get_error() : String(),
script_lang && (script_lang->debug_get_stack_level_count() > 0),
error_str,
script_lang->debug_get_stack_level_count() > 0,
Thread::get_caller_id()
};
if (allow_focus_steal_fn) {
allow_focus_steal_fn();
}
send_message("debug_enter", msg);
} else {
ERR_PRINT(error_str);
return;
}
Input::MouseMode mouse_mode = Input::MouseMode::MOUSE_MODE_VISIBLE;
Input::MouseMode mouse_mode = Input::MOUSE_MODE_VISIBLE;
if (Thread::is_main_thread()) {
if (Thread::get_caller_id() == Thread::get_main_id()) {
mouse_mode = Input::get_singleton()->get_mouse_mode();
if (mouse_mode != Input::MouseMode::MOUSE_MODE_VISIBLE) {
Input::get_singleton()->set_mouse_mode(Input::MouseMode::MOUSE_MODE_VISIBLE);
if (mouse_mode != Input::MOUSE_MODE_VISIBLE) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
}
} else {
MutexLock mutex_lock(mutex);
@ -465,11 +465,6 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
script_debugger->set_lines_left(1);
break;
} else if (command == "out") {
script_debugger->set_depth(1);
script_debugger->set_lines_left(1);
break;
} else if (command == "continue") {
script_debugger->set_depth(-1);
script_debugger->set_lines_left(-1);
@ -481,7 +476,6 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
} else if (command == "get_stack_dump") {
DebuggerMarshalls::ScriptStackDump dump;
if (script_lang) {
int slc = script_lang->debug_get_stack_level_count();
for (int i = 0; i < slc; i++) {
ScriptLanguage::StackInfo frame;
@ -490,15 +484,11 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
frame.func = script_lang->debug_get_stack_level_function(i);
dump.frames.push_back(frame);
}
}
send_message("stack_dump", dump.serialize());
} else if (command == "get_stack_frame_vars") {
ERR_FAIL_COND(data.size() != 1);
if (!script_lang) {
send_message("stack_frame_vars", Array{ 0 });
continue;
}
ERR_FAIL_NULL(script_lang);
int lv = data[0];
List<String> members;
@ -554,60 +544,25 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
break;
}
PackedStringArray input_names;
Array input_vals;
List<String> locals;
List<Variant> local_vals;
script_debugger->get_break_language()->debug_get_stack_level_locals(frame, &locals, &local_vals);
ERR_FAIL_COND(locals.size() != local_vals.size());
PackedStringArray locals_vector;
for (const String &S : locals) {
input_names.append(S);
locals_vector.append(S);
}
Array local_vals_array;
for (const Variant &V : local_vals) {
input_vals.append(V);
}
List<String> globals;
List<Variant> globals_vals;
script_debugger->get_break_language()->debug_get_globals(&globals, &globals_vals);
ERR_FAIL_COND(globals.size() != globals_vals.size());
for (const String &S : globals) {
input_names.append(S);
}
for (const Variant &V : globals_vals) {
input_vals.append(V);
}
LocalVector<StringName> native_types;
ClassDB::get_class_list(native_types);
for (const StringName &class_name : native_types) {
if (!ClassDB::is_class_exposed(class_name) || !Engine::get_singleton()->has_singleton(class_name) || Engine::get_singleton()->is_singleton_editor_only(class_name)) {
continue;
}
input_names.append(class_name);
input_vals.append(Engine::get_singleton()->get_singleton_object(class_name));
}
LocalVector<StringName> user_types;
ScriptServer::get_global_class_list(user_types);
for (const StringName &class_name : user_types) {
String scr_path = ScriptServer::get_global_class_path(class_name);
Ref<Script> scr = ResourceLoader::load(scr_path, "Script");
ERR_CONTINUE_MSG(scr.is_null(), vformat(R"(Could not load the global class %s from resource path: "%s".)", class_name, scr_path));
input_names.append(class_name);
input_vals.append(scr);
local_vals_array.append(V);
}
Expression expression;
expression.parse(expression_str, input_names);
const Variant return_val = expression.execute(input_vals, breaked_instance->get_owner());
expression.parse(expression_str, locals_vector);
const Variant return_val = expression.execute(local_vals_array, breaked_instance->get_owner());
DebuggerMarshalls::ScriptStackVariable stvar;
stvar.name = expression_str;
@ -624,7 +579,7 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
}
} else {
OS::get_singleton()->delay_usec(10000);
if (Thread::is_main_thread()) {
if (Thread::get_caller_id() == Thread::get_main_id()) {
// If this is a busy loop on the main thread, events still need to be processed.
DisplayServer::get_singleton()->force_process_and_drop_events();
}
@ -633,29 +588,20 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
send_message("debug_exit", Array());
if (Thread::is_main_thread() && mouse_mode != Input::MouseMode::MOUSE_MODE_VISIBLE) {
if (Thread::get_caller_id() == Thread::get_main_id()) {
if (mouse_mode != Input::MOUSE_MODE_VISIBLE) {
Input::get_singleton()->set_mouse_mode(mouse_mode);
}
{
} else {
MutexLock mutex_lock(mutex);
if (!Thread::is_main_thread()) {
messages.erase(Thread::get_caller_id());
}
threads_in_break.erase(Thread::get_caller_id());
}
}
void RemoteDebugger::poll_events(bool p_is_idle) {
{
MutexLock lock(mutex);
if (threads_in_break.has(Thread::get_caller_id())) {
// We're already in `RemoteDebugger::debug`, so messages should be handled there instead.
if (peer.is_null()) {
return;
}
}
flush_output();
@ -694,18 +640,10 @@ void RemoteDebugger::poll_events(bool p_is_idle) {
reload_all_scripts = false;
} else if (!script_paths_to_reload.is_empty()) {
Array scripts_to_reload;
for (const Variant &v : script_paths_to_reload) {
const String &path = v;
for (int i = 0; i < script_paths_to_reload.size(); ++i) {
String path = script_paths_to_reload[i];
Error err = OK;
Ref<Script> script = ResourceCache::get_ref(path);
if (script.is_null()) {
if (path.is_resource_file()) {
script = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err);
} else {
// Built-in script that isn't in ResourceCache, no need to reload.
continue;
}
}
Ref<Script> script = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err);
ERR_CONTINUE_MSG(err != OK, vformat("Could not reload script '%s': %s", path, error_names[err]));
ERR_CONTINUE_MSG(script.is_null(), vformat("Could not reload script '%s': Not a script!", path, error_names[err]));
scripts_to_reload.push_back(script);

View file

@ -33,6 +33,8 @@
#include "core/debugger/debugger_marshalls.h"
#include "core/debugger/engine_debugger.h"
#include "core/debugger/remote_debugger_peer.h"
#include "core/object/class_db.h"
#include "core/string/string_name.h"
#include "core/string/ustring.h"
#include "core/variant/array.h"
@ -84,7 +86,6 @@ private:
};
HashMap<Thread::ID, List<Message>> messages;
HashSet<Thread::ID> threads_in_break;
void _poll_messages();
bool _has_messages();
@ -105,6 +106,9 @@ private:
Error _profiler_capture(const String &p_cmd, const Array &p_data, bool &r_captured);
Error _core_capture(const String &p_cmd, const Array &p_data, bool &r_captured);
template <typename T>
void _bind_profiler(const String &p_name, T *p_prof);
Error _try_capture(const String &p_name, const Array &p_data, bool &r_captured);
public:

View file

@ -32,9 +32,6 @@
#include "core/config/project_settings.h"
#include "core/io/marshalls.h"
#include "core/io/stream_peer_socket.h"
#include "core/io/stream_peer_tcp.h"
#include "core/io/stream_peer_uds.h"
#include "core/os/os.h"
bool RemoteDebuggerPeerTCP::is_peer_connected() {
@ -47,10 +44,8 @@ bool RemoteDebuggerPeerTCP::has_message() {
Array RemoteDebuggerPeerTCP::get_message() {
MutexLock lock(mutex);
List<Array>::Element *E = in_queue.front();
ERR_FAIL_NULL_V_MSG(E, Array(), "No remote debugger messages in queue.");
Array out = E->get();
ERR_FAIL_COND_V(!has_message(), Array());
Array out = in_queue.front()->get();
in_queue.pop_front();
return out;
}
@ -79,19 +74,18 @@ void RemoteDebuggerPeerTCP::close() {
in_buf.clear();
}
RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP() {
RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_tcp) {
// This means remote debugger takes 16 MiB just because it exists...
in_buf.resize((8 << 20) + 4); // 8 MiB should be way more than enough (need 4 extra bytes for encoding packet size).
out_buf.resize(8 << 20); // 8 MiB should be way more than enough
}
RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP(Ref<StreamPeerSocket> p_stream) :
RemoteDebuggerPeerTCP() {
DEV_ASSERT(p_stream.is_valid());
tcp_client = p_stream;
tcp_client = p_tcp;
if (tcp_client.is_valid()) { // Attaching to an already connected stream.
connected = true;
running = true;
thread.start(_thread_func, this);
} else {
tcp_client.instantiate();
}
}
RemoteDebuggerPeerTCP::~RemoteDebuggerPeerTCP() {
@ -102,13 +96,11 @@ void RemoteDebuggerPeerTCP::_write_out() {
while (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED && tcp_client->wait(NetSocket::POLL_TYPE_OUT) == OK) {
uint8_t *buf = out_buf.ptrw();
if (out_left <= 0) {
mutex.lock();
List<Array>::Element *E = out_queue.front();
if (!E) {
mutex.unlock();
break;
if (out_queue.is_empty()) {
break; // Nothing left to send
}
Variant var = E->get();
mutex.lock();
Variant var = out_queue.front()->get();
out_queue.pop_front();
mutex.unlock();
int size = 0;
@ -158,10 +150,21 @@ void RemoteDebuggerPeerTCP::_read_in() {
}
}
Error RemoteDebuggerPeerTCP::_try_connect(Ref<StreamPeerSocket> tcp_client) {
Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_port) {
IPAddress ip;
if (p_host.is_valid_ip_address()) {
ip = p_host;
} else {
ip = IP::get_singleton()->resolve_hostname(p_host);
}
int port = p_port;
const int tries = 6;
const int waits[tries] = { 1, 10, 100, 1000, 1000, 1000 };
tcp_client->connect_to_host(ip, port);
for (int i = 0; i < tries; i++) {
tcp_client->poll();
if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
@ -178,6 +181,9 @@ Error RemoteDebuggerPeerTCP::_try_connect(Ref<StreamPeerSocket> tcp_client) {
ERR_PRINT(vformat("Remote Debugger: Unable to connect. Status: %s.", String::num_int64(tcp_client->get_status())));
return FAILED;
}
connected = true;
running = true;
thread.start(_thread_func, this);
return OK;
}
@ -211,7 +217,7 @@ void RemoteDebuggerPeerTCP::_poll() {
}
}
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create_tcp(const String &p_uri) {
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create(const String &p_uri) {
ERR_FAIL_COND_V(!p_uri.begins_with("tcp://"), nullptr);
String debug_host = p_uri.replace("tcp://", "");
@ -223,30 +229,13 @@ RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create_tcp(const String &p_uri) {
debug_host = debug_host.substr(0, sep_pos);
}
IPAddress ip;
if (debug_host.is_valid_ip_address()) {
ip = debug_host;
} else {
ip = IP::get_singleton()->resolve_hostname(debug_host);
RemoteDebuggerPeerTCP *peer = memnew(RemoteDebuggerPeerTCP);
Error err = peer->connect_to_host(debug_host, debug_port);
if (err != OK) {
memdelete(peer);
return nullptr;
}
Ref<StreamPeerTCP> stream;
stream.instantiate();
ERR_FAIL_COND_V_MSG(stream->connect_to_host(ip, debug_port) != OK, nullptr, vformat("Remote Debugger: Unable to connect to host '%s:%d'.", debug_host, debug_port));
ERR_FAIL_COND_V(_try_connect(stream), nullptr);
return memnew(RemoteDebuggerPeerTCP(stream));
}
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create_unix(const String &p_uri) {
ERR_FAIL_COND_V(!p_uri.begins_with("unix://"), nullptr);
String debug_path = p_uri.replace("unix://", "");
Ref<StreamPeerUDS> stream;
stream.instantiate();
Error err = stream->connect_to_host(debug_path);
ERR_FAIL_COND_V_MSG(err != OK && err != ERR_BUSY, nullptr, vformat("Remote Debugger: Unable to connect to socket path '%s'.", debug_path));
ERR_FAIL_COND_V(_try_connect(stream), nullptr);
return memnew(RemoteDebuggerPeerTCP(stream));
return peer;
}
RemoteDebuggerPeer::RemoteDebuggerPeer() {

View file

@ -30,16 +30,13 @@
#pragma once
#include "core/io/stream_peer_tcp.h"
#include "core/object/ref_counted.h"
#include "core/os/mutex.h"
#include "core/os/thread.h"
#include "core/string/ustring.h"
class StreamPeerSocket;
class RemoteDebuggerPeer : public RefCounted {
GDSOFTCLASS(RemoteDebuggerPeer, RefCounted);
protected:
int max_queued_messages = 4096;
@ -57,10 +54,8 @@ public:
};
class RemoteDebuggerPeerTCP : public RemoteDebuggerPeer {
GDSOFTCLASS(RemoteDebuggerPeerTCP, RemoteDebuggerPeer);
private:
Ref<StreamPeerSocket> tcp_client;
Ref<StreamPeerTCP> tcp_client;
Mutex mutex;
Thread thread;
List<Array> in_queue;
@ -79,11 +74,11 @@ private:
void _poll();
void _write_out();
void _read_in();
static Error _try_connect(Ref<StreamPeerSocket> p_stream);
public:
static RemoteDebuggerPeer *create_tcp(const String &p_uri);
static RemoteDebuggerPeer *create_unix(const String &p_uri);
static RemoteDebuggerPeer *create(const String &p_uri);
Error connect_to_host(const String &p_host, uint16_t p_port);
bool is_peer_connected() override;
int get_max_message_size() const override;
@ -93,7 +88,6 @@ public:
void poll() override;
void close() override;
RemoteDebuggerPeerTCP(Ref<StreamPeerSocket> p_stream);
RemoteDebuggerPeerTCP();
RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_stream = Ref<StreamPeerTCP>());
~RemoteDebuggerPeerTCP();
};

View file

@ -32,6 +32,9 @@
#include "core/debugger/engine_debugger.h"
thread_local int ScriptDebugger::lines_left = -1;
thread_local int ScriptDebugger::depth = -1;
thread_local ScriptLanguage *ScriptDebugger::break_lang = nullptr;
thread_local Vector<ScriptDebugger::StackInfo> ScriptDebugger::error_stack_info;
void ScriptDebugger::set_lines_left(int p_left) {

View file

@ -43,9 +43,9 @@ class ScriptDebugger {
HashMap<int, HashSet<StringName>> breakpoints;
static inline thread_local int lines_left = -1;
static inline thread_local int depth = -1;
static inline thread_local ScriptLanguage *break_lang = nullptr;
static thread_local int lines_left;
static thread_local int depth;
static thread_local ScriptLanguage *break_lang;
static thread_local Vector<StackInfo> error_stack_info;
public:
@ -82,4 +82,5 @@ public:
void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info);
Vector<StackInfo> get_error_stack_info() const;
ScriptDebugger() {}
};

View file

@ -30,27 +30,11 @@
#include "doc_data.h"
#include "core/object/object.h"
String DocData::get_default_value_string(const Variant &p_value) {
const Variant::Type type = p_value.get_type();
if (type == Variant::ARRAY) {
if (p_value.get_type() == Variant::ARRAY) {
return Variant(Array(p_value, 0, StringName(), Variant())).get_construct_string().replace_char('\n', ' ');
} else if (type == Variant::DICTIONARY) {
} else if (p_value.get_type() == Variant::DICTIONARY) {
return Variant(Dictionary(p_value, 0, StringName(), Variant(), 0, StringName(), Variant())).get_construct_string().replace_char('\n', ' ');
} else if (type == Variant::INT) {
return itos(p_value);
} else if (type == Variant::FLOAT) {
// Since some values are 32-bit internally, use 32-bit for all
// documentation values to avoid garbage digits at the end.
const String s = String::num_scientific((float)p_value);
// Use float literals for floats in the documentation for clarity.
if (s != "inf" && s != "-inf" && s != "nan") {
if (!s.contains_char('.') && !s.contains_char('e')) {
return s + ".0";
}
}
return s;
} else {
return p_value.get_construct_string().replace_char('\n', ' ');
}
@ -129,13 +113,6 @@ void DocData::method_doc_from_methodinfo(DocData::MethodDoc &p_method, const Met
p_method.qualifiers = "virtual";
}
if (p_methodinfo.flags & METHOD_FLAG_VIRTUAL_REQUIRED) {
if (!p_method.qualifiers.is_empty()) {
p_method.qualifiers += " ";
}
p_method.qualifiers += "required";
}
if (p_methodinfo.flags & METHOD_FLAG_CONST) {
if (!p_method.qualifiers.is_empty()) {
p_method.qualifiers += " ";

View file

@ -30,6 +30,7 @@
#pragma once
#include "core/io/xml_parser.h"
#include "core/variant/variant.h"
class DocData {
@ -106,8 +107,6 @@ public:
bool is_experimental = false;
String experimental_message;
Vector<ArgumentDoc> arguments;
// NOTE: Only for GDScript for now. The rest argument is not saved to the XML file.
ArgumentDoc rest_argument;
Vector<int> errors_returned;
String keywords;
bool operator<(const MethodDoc &p_method) const {

View file

@ -30,59 +30,58 @@
#include "error_list.h"
#include "core/string/ustring.h"
#include "core/typedefs.h"
#include <iterator>
const char *error_names[] = {
TTRC("OK"), // OK
TTRC("Failed"), // FAILED
TTRC("Unavailable"), // ERR_UNAVAILABLE
TTRC("Unconfigured"), // ERR_UNCONFIGURED
TTRC("Unauthorized"), // ERR_UNAUTHORIZED
TTRC("Parameter out of range"), // ERR_PARAMETER_RANGE_ERROR
TTRC("Out of memory"), // ERR_OUT_OF_MEMORY
TTRC("File not found"), // ERR_FILE_NOT_FOUND
TTRC("File: Bad drive"), // ERR_FILE_BAD_DRIVE
TTRC("File: Bad path"), // ERR_FILE_BAD_PATH
TTRC("File: Permission denied"), // ERR_FILE_NO_PERMISSION
TTRC("File already in use"), // ERR_FILE_ALREADY_IN_USE
TTRC("Can't open file"), // ERR_FILE_CANT_OPEN
TTRC("Can't write file"), // ERR_FILE_CANT_WRITE
TTRC("Can't read file"), // ERR_FILE_CANT_READ
TTRC("File unrecognized"), // ERR_FILE_UNRECOGNIZED
TTRC("File corrupt"), // ERR_FILE_CORRUPT
TTRC("Missing dependencies for file"), // ERR_FILE_MISSING_DEPENDENCIES
TTRC("End of file"), // ERR_FILE_EOF
TTRC("Can't open"), // ERR_CANT_OPEN
TTRC("Can't create"), // ERR_CANT_CREATE
TTRC("Query failed"), // ERR_QUERY_FAILED
TTRC("Already in use"), // ERR_ALREADY_IN_USE
TTRC("Locked"), // ERR_LOCKED
TTRC("Timeout"), // ERR_TIMEOUT
TTRC("Can't connect"), // ERR_CANT_CONNECT
TTRC("Can't resolve"), // ERR_CANT_RESOLVE
TTRC("Connection error"), // ERR_CONNECTION_ERROR
TTRC("Can't acquire resource"), // ERR_CANT_ACQUIRE_RESOURCE
TTRC("Can't fork"), // ERR_CANT_FORK
TTRC("Invalid data"), // ERR_INVALID_DATA
TTRC("Invalid parameter"), // ERR_INVALID_PARAMETER
TTRC("Already exists"), // ERR_ALREADY_EXISTS
TTRC("Does not exist"), // ERR_DOES_NOT_EXIST
TTRC("Can't read database"), // ERR_DATABASE_CANT_READ
TTRC("Can't write database"), // ERR_DATABASE_CANT_WRITE
TTRC("Compilation failed"), // ERR_COMPILATION_FAILED
TTRC("Method not found"), // ERR_METHOD_NOT_FOUND
TTRC("Link failed"), // ERR_LINK_FAILED
TTRC("Script failed"), // ERR_SCRIPT_FAILED
TTRC("Cyclic link detected"), // ERR_CYCLIC_LINK
TTRC("Invalid declaration"), // ERR_INVALID_DECLARATION
TTRC("Duplicate symbol"), // ERR_DUPLICATE_SYMBOL
TTRC("Parse error"), // ERR_PARSE_ERROR
TTRC("Busy"), // ERR_BUSY
TTRC("Skip"), // ERR_SKIP
TTRC("Help"), // ERR_HELP
TTRC("Bug"), // ERR_BUG
TTRC("Printer on fire"), // ERR_PRINTER_ON_FIRE
"OK", // OK
"Failed", // FAILED
"Unavailable", // ERR_UNAVAILABLE
"Unconfigured", // ERR_UNCONFIGURED
"Unauthorized", // ERR_UNAUTHORIZED
"Parameter out of range", // ERR_PARAMETER_RANGE_ERROR
"Out of memory", // ERR_OUT_OF_MEMORY
"File not found", // ERR_FILE_NOT_FOUND
"File: Bad drive", // ERR_FILE_BAD_DRIVE
"File: Bad path", // ERR_FILE_BAD_PATH
"File: Permission denied", // ERR_FILE_NO_PERMISSION
"File already in use", // ERR_FILE_ALREADY_IN_USE
"Can't open file", // ERR_FILE_CANT_OPEN
"Can't write file", // ERR_FILE_CANT_WRITE
"Can't read file", // ERR_FILE_CANT_READ
"File unrecognized", // ERR_FILE_UNRECOGNIZED
"File corrupt", // ERR_FILE_CORRUPT
"Missing dependencies for file", // ERR_FILE_MISSING_DEPENDENCIES
"End of file", // ERR_FILE_EOF
"Can't open", // ERR_CANT_OPEN
"Can't create", // ERR_CANT_CREATE
"Query failed", // ERR_QUERY_FAILED
"Already in use", // ERR_ALREADY_IN_USE
"Locked", // ERR_LOCKED
"Timeout", // ERR_TIMEOUT
"Can't connect", // ERR_CANT_CONNECT
"Can't resolve", // ERR_CANT_RESOLVE
"Connection error", // ERR_CONNECTION_ERROR
"Can't acquire resource", // ERR_CANT_ACQUIRE_RESOURCE
"Can't fork", // ERR_CANT_FORK
"Invalid data", // ERR_INVALID_DATA
"Invalid parameter", // ERR_INVALID_PARAMETER
"Already exists", // ERR_ALREADY_EXISTS
"Does not exist", // ERR_DOES_NOT_EXIST
"Can't read database", // ERR_DATABASE_CANT_READ
"Can't write database", // ERR_DATABASE_CANT_WRITE
"Compilation failed", // ERR_COMPILATION_FAILED
"Method not found", // ERR_METHOD_NOT_FOUND
"Link failed", // ERR_LINK_FAILED
"Script failed", // ERR_SCRIPT_FAILED
"Cyclic link detected", // ERR_CYCLIC_LINK
"Invalid declaration", // ERR_INVALID_DECLARATION
"Duplicate symbol", // ERR_DUPLICATE_SYMBOL
"Parse error", // ERR_PARSE_ERROR
"Busy", // ERR_BUSY
"Skip", // ERR_SKIP
"Help", // ERR_HELP
"Bug", // ERR_BUG
"Printer on fire", // ERR_PRINTER_ON_FIRE
};
static_assert(std_size(error_names) == ERR_MAX);
static_assert(std::size(error_names) == ERR_MAX);

View file

@ -40,7 +40,7 @@
* - 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/main/java/org/godotengine/godot/error/Error.kt
* - Have a matching Android version in platform/android/java/lib/src/org/godotengine/godot/error/Error.kt
*/
enum Error {

View file

@ -32,12 +32,9 @@
#include "core/io/logger.h"
#include "core/object/object_id.h"
#include "core/object/script_language.h"
#include "core/os/os.h"
#include "core/string/ustring.h"
#include <cstdio>
// 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"
@ -45,19 +42,6 @@
#endif
static ErrorHandlerList *error_handler_list = nullptr;
static thread_local bool is_printing_error = false;
static void _err_print_fallback(const char *p_function, const char *p_file, int p_line, const char *p_error_details, ErrorHandlerType p_type, bool p_reentrance) {
if (p_reentrance) {
fprintf(stderr, "While attempting to print an error, another error was printed:\n");
}
fprintf(stderr, "%s: %s\n", _error_handler_type_string(p_type), p_error_details);
if (p_function && p_file) {
fprintf(stderr, " at: %s (%s:%i)\n", p_function, p_file, p_line);
}
}
void add_error_handler(ErrorHandlerList *p_handler) {
// If p_handler is already in error_handler_list
@ -106,25 +90,15 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co
// Main error printing function.
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) {
if (is_printing_error) {
// Fallback if we're already printing an error, to prevent infinite recursion.
const char *err_details = (p_message && *p_message) ? p_message : p_error;
_err_print_fallback(p_function, p_file, p_line, err_details, p_type, true);
return;
}
is_printing_error = true;
if (OS::get_singleton()) {
OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, p_editor_notify, (Logger::ErrorType)p_type, ScriptServer::capture_script_backtraces(false));
OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, p_editor_notify, (Logger::ErrorType)p_type);
} else {
// Fallback if errors happen before OS init or after it's destroyed.
const char *err_details = (p_message && *p_message) ? p_message : p_error;
_err_print_fallback(p_function, p_file, p_line, err_details, p_type, false);
fprintf(stderr, "ERROR: %s\n at: %s (%s:%i)\n", err_details, p_function, p_file, p_line);
}
_global_lock();
ErrorHandlerList *l = error_handler_list;
while (l) {
l->errfunc(l->userdata, p_function, p_file, p_line, p_error, p_message, p_editor_notify, p_type);
@ -132,42 +106,28 @@ void _err_print_error(const char *p_function, const char *p_file, int p_line, co
}
_global_unlock();
is_printing_error = false;
}
// For printing errors when we may crash at any point, so we must flush ASAP a lot of lines
// but we don't want to make it noisy by printing lots of file & line info (because it's already
// been printing by a preceding _err_print_error).
void _err_print_error_asap(const String &p_error, ErrorHandlerType p_type) {
const char *err_details = p_error.utf8().get_data();
if (is_printing_error) {
// Fallback if we're already printing an error, to prevent infinite recursion.
_err_print_fallback(nullptr, nullptr, 0, err_details, p_type, true);
return;
}
is_printing_error = true;
if (OS::get_singleton()) {
OS::get_singleton()->printerr("%s: %s\n", _error_handler_type_string(p_type), err_details);
OS::get_singleton()->printerr("ERROR: %s\n", p_error.utf8().get_data());
} else {
// Fallback if errors happen before OS init or after it's destroyed.
_err_print_fallback(nullptr, nullptr, 0, err_details, p_type, false);
const char *err_details = p_error.utf8().get_data();
fprintf(stderr, "ERROR: %s\n", err_details);
}
_global_lock();
ErrorHandlerList *l = error_handler_list;
while (l) {
l->errfunc(l->userdata, "", "", 0, err_details, "", false, p_type);
l->errfunc(l->userdata, "", "", 0, p_error.utf8().get_data(), "", false, p_type);
l = l->next;
}
_global_unlock();
is_printing_error = false;
}
// Errors with message. (All combinations of p_error and p_message as String or char*.)

View file

@ -32,6 +32,8 @@
#include "core/typedefs.h"
#include <atomic> // IWYU pragma: keep // Used in macro. We'd normally use `safe_refcount.h`, but that would cause circular includes.
class String;
class ObjectID;
@ -42,20 +44,6 @@ enum ErrorHandlerType {
ERR_HANDLER_SHADER,
};
constexpr const char *_error_handler_type_string(ErrorHandlerType p_type) {
switch (p_type) {
case ERR_HANDLER_ERROR:
return "ERROR";
case ERR_HANDLER_WARNING:
return "WARNING";
case ERR_HANDLER_SCRIPT:
return "SCRIPT ERROR";
case ERR_HANDLER_SHADER:
return "SHADER ERROR";
}
return "UNKNOWN ERROR";
}
// Pointer to the error handler printing function. Reassign to any function to have errors printed.
// Parameters: userdata, function, file, line, error, explanation, type.
typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, bool p_editor_notify, ErrorHandlerType p_type);
@ -65,6 +53,8 @@ struct ErrorHandlerList {
void *userdata = nullptr;
ErrorHandlerList *next = nullptr;
ErrorHandlerList() {}
};
void add_error_handler(ErrorHandlerList *p_handler);
@ -91,7 +81,7 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
#define FUNCTION_STR __FUNCTION__
#endif
#if defined(_MSC_VER) && !defined(__clang__)
#ifdef _MSC_VER
/**
* Don't use GENERATE_TRAP() directly, should only be used be the macros below.
*/
@ -288,7 +278,7 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
((void)0)
/**
* Same as `ERR_FAIL_UNSIGNED_INDEX_V_MSG` but also notifies the editor.
* Same as `ERR_FAIL_UNSIGNED_INDEX_V_EDMSG` but also notifies the editor.
*/
#define ERR_FAIL_UNSIGNED_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
if (unlikely((m_index) >= (m_size))) { \
@ -678,10 +668,10 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
*/
#define ERR_PRINT_ONCE(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
static bool first_print = true; \
if (first_print) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg); \
first_print = false; \
} \
} else \
((void)0)
@ -691,10 +681,10 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
*/
#define ERR_PRINT_ONCE_ED(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
static bool first_print = true; \
if (first_print) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true); \
first_print = false; \
} \
} else \
((void)0)
@ -722,10 +712,10 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
*/
#define WARN_PRINT_ONCE(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
static bool first_print = true; \
if (first_print) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, ERR_HANDLER_WARNING); \
first_print = false; \
} \
} else \
((void)0)
@ -735,10 +725,10 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
*/
#define WARN_PRINT_ONCE_ED(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
static bool first_print = true; \
if (first_print) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, ERR_HANDLER_WARNING); \
first_print = false; \
} \
} else \
((void)0)
@ -760,10 +750,10 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
*/
#define WARN_DEPRECATED \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
static std::atomic<bool> warning_shown; \
if (!warning_shown.load()) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", false, ERR_HANDLER_WARNING); \
warning_shown.store(true); \
} \
} else \
((void)0)
@ -773,10 +763,10 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
*/
#define WARN_DEPRECATED_MSG(m_msg) \
if (true) { \
static bool warning_shown = false; \
if (unlikely(!warning_shown)) { \
warning_shown = true; \
static std::atomic<bool> warning_shown; \
if (!warning_shown.load()) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, false, ERR_HANDLER_WARNING); \
warning_shown.store(true); \
} \
} else \
((void)0)
@ -837,12 +827,8 @@ void _physics_interpolation_warning(const char *p_function, const char *p_file,
#ifdef DEV_ENABLED
#define DEV_CHECK_ONCE(m_cond) \
if (true) { \
static bool first_print = true; \
if (first_print && unlikely(!(m_cond))) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "DEV_CHECK_ONCE failed \"" _STR(m_cond) "\" is false."); \
first_print = false; \
} \
if (unlikely(!(m_cond))) { \
ERR_PRINT_ONCE("DEV_CHECK_ONCE failed \"" _STR(m_cond) "\" is false."); \
} else \
((void)0)
#else

View file

@ -4,20 +4,14 @@ from misc.utility.scons_hints import *
Import("env")
import make_interface_dumper
import make_interface_header
import make_wrappers
env.CommandNoCache("ext_wrappers.gen.h", "make_wrappers.py", env.Run(make_wrappers.run))
env.CommandNoCache(["ext_wrappers.gen.inc"], "make_wrappers.py", env.Run(make_wrappers.run))
env.CommandNoCache(
"gdextension_interface_dump.gen.h",
["gdextension_interface.json", "make_interface_dumper.py"],
["gdextension_interface.h", "make_interface_dumper.py"],
env.Run(make_interface_dumper.run),
)
env.CommandNoCache(
"gdextension_interface.gen.h",
["gdextension_interface.json", "make_interface_header.py"],
env.Run(make_interface_header.run),
)
env_extension = env.Clone()

View file

@ -35,12 +35,11 @@
#include "core/extension/gdextension_special_compat_hashes.h"
#include "core/io/file_access.h"
#include "core/io/json.h"
#include "core/object/class_db.h"
#include "core/templates/pair.h"
#include "core/version.h"
#ifdef TOOLS_ENABLED
#include "editor/doc/editor_help.h"
#include "editor/editor_help.h"
static String get_builtin_or_variant_type_name(const Variant::Type p_type) {
if (p_type == Variant::NIL) {
@ -89,7 +88,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[14] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double", "char16", "char32", "required" };
static const char *argmeta[13] = { "none", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double", "char16", "char32" };
return argmeta[metadata];
}
@ -97,7 +96,7 @@ static String fix_doc_description(const String &p_bbcode) {
// Based on what EditorHelp does.
return p_bbcode.dedent()
.remove_chars("\r")
.remove_chars("\t\r")
.strip_edges();
}
@ -798,17 +797,6 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
d2["is_static"] = Variant::is_builtin_method_static(type, method_name);
d2["hash"] = Variant::get_builtin_method_hash(type, method_name);
Vector<uint32_t> compat_hashes = Variant::get_builtin_method_compatibility_hashes(type, method_name);
Array compatibility;
if (compat_hashes.size()) {
for (int j = 0; j < compat_hashes.size(); j++) {
compatibility.push_back(compat_hashes[j]);
}
}
if (compatibility.size() > 0) {
d2["hash_compatibility"] = compatibility;
}
Vector<Variant> default_args = Variant::get_builtin_method_default_arguments(type, method_name);
Array arguments;
@ -912,9 +900,11 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
// classes
Array classes;
LocalVector<StringName> class_list;
List<StringName> class_list;
ClassDB::get_class_list(class_list);
ClassDB::get_class_list(&class_list);
class_list.sort_custom<StringName::AlphCompare>();
for (const StringName &class_name : class_list) {
if (!ClassDB::is_class_exposed(class_name)) {
@ -1183,10 +1173,6 @@ Dictionary GDExtensionAPIDump::generate_extension_api(bool p_include_docs) {
List<MethodInfo> signal_list;
ClassDB::get_signal_list(class_name, &signal_list, true);
for (const MethodInfo &F : signal_list) {
if (F.name.begins_with("_")) {
continue; // Hidden signal.
}
StringName signal_name = F.name;
Dictionary d2;
d2["name"] = String(signal_name);

View file

@ -30,11 +30,9 @@
#pragma once
#ifdef TOOLS_ENABLED
#include "core/extension/gdextension.h"
#include "core/error/error_list.h"
#include "core/string/ustring.h"
#include "core/variant/dictionary.h"
#ifdef TOOLS_ENABLED
class GDExtensionAPIDump {
public:
@ -42,5 +40,4 @@ public:
static void generate_extension_json_file(const String &p_path, bool p_include_docs = false);
static Error validate_extension_json_file(const String &p_path);
};
#endif

View file

@ -30,10 +30,6 @@
#ifndef DISABLE_DEPRECATED
#include "gdextension.h"
#include "core/object/class_db.h"
Error GDExtension::_open_library_bind_compat_88418(const String &p_path, const String &p_entry_symbol) {
return ERR_UNAVAILABLE;
}
@ -50,4 +46,4 @@ void GDExtension::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("initialize_library", "level"), &GDExtension::_initialize_library_bind_compat_88418);
}
#endif // DISABLE_DEPRECATED
#endif

View file

@ -32,7 +32,6 @@
#include "gdextension.compat.inc"
#include "core/config/project_settings.h"
#include "core/object/callable_mp.h"
#include "core/object/class_db.h"
#include "core/object/method_bind.h"
#include "gdextension_library_loader.h"
@ -88,7 +87,7 @@ public:
virtual bool is_valid() const override { return valid; }
#endif
#ifdef DEBUG_ENABLED
#ifdef DEBUG_METHODS_ENABLED
virtual GodotTypeInfo::Metadata get_argument_meta(int p_arg) const override {
if (p_arg < 0) {
return return_value_metadata;
@ -96,7 +95,7 @@ public:
return arguments_metadata.get(p_arg);
}
}
#endif // DEBUG_ENABLED
#endif
virtual Variant call(Object *p_object, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) const override {
#ifdef TOOLS_ENABLED
@ -220,9 +219,9 @@ public:
_set_returns(p_method_info->has_return_value);
_set_const(p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_CONST);
_set_static(p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_STATIC);
#ifdef DEBUG_ENABLED
#ifdef DEBUG_METHODS_ENABLED
_generate_argument_types(p_method_info->argument_count);
#endif // DEBUG_ENABLED
#endif
set_argument_count(p_method_info->argument_count);
Vector<Variant> defargs;
@ -241,7 +240,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 GDExtensionClassCreationInfo5 class_info5 = {
const GDExtensionClassCreationInfo4 class_info4 = {
p_extension_funcs->is_virtual, // GDExtensionBool is_virtual;
p_extension_funcs->is_abstract, // GDExtensionBool is_abstract;
true, // GDExtensionBool is_exposed;
@ -268,7 +267,6 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library
};
const ClassCreationDeprecatedInfo legacy = {
false,
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;
@ -276,11 +274,11 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library
p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
nullptr,
};
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info5, &legacy);
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info4, &legacy);
}
void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo2 *p_extension_funcs) {
const GDExtensionClassCreationInfo5 class_info5 = {
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;
@ -307,7 +305,6 @@ void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_librar
};
const ClassCreationDeprecatedInfo legacy = {
!p_extension_funcs->is_exposed, // bool legacy_unexposed_class;
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;
@ -315,11 +312,11 @@ void GDExtension::_register_extension_class2(GDExtensionClassLibraryPtr p_librar
p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
p_extension_funcs->get_virtual_call_data_func, // GDExtensionClassGetVirtual get_virtual_func;
};
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info5, &legacy);
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info4, &legacy);
}
void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo3 *p_extension_funcs) {
const GDExtensionClassCreationInfo5 class_info5 = {
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;
@ -346,7 +343,6 @@ void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_librar
};
const ClassCreationDeprecatedInfo legacy = {
!p_extension_funcs->is_exposed, // bool legacy_unexposed_class;
nullptr, // GDExtensionClassNotification notification_func;
nullptr, // GDExtensionClassFreePropertyList free_property_list_func;
p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance2 create_instance_func;
@ -354,29 +350,16 @@ void GDExtension::_register_extension_class3(GDExtensionClassLibraryPtr p_librar
p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func;
p_extension_funcs->get_virtual_call_data_func, // GDExtensionClassGetVirtual get_virtual_func;
};
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info5, &legacy);
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info4, &legacy);
}
void GDExtension::_register_extension_class4(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs) {
GDExtensionClassCreationInfo5 class_info5 = *p_extension_funcs;
const ClassCreationDeprecatedInfo legacy = {
!p_extension_funcs->is_exposed, // bool legacy_unexposed_class;
nullptr, // GDExtensionClassNotification notification_func;
nullptr, // GDExtensionClassFreePropertyList free_property_list_func;
nullptr, // GDExtensionClassCreateInstance2 create_instance_func;
nullptr, // GDExtensionClassGetRID get_rid;
nullptr, // GDExtensionClassGetVirtual get_virtual_func;
nullptr, // GDExtensionClassGetVirtual get_virtual_func;
};
_register_extension_class_internal(p_library, p_class_name, p_parent_class_name, &class_info5, &legacy);
}
#endif // DISABLE_DEPRECATED
void GDExtension::_register_extension_class5(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo5 *p_extension_funcs) {
void GDExtension::_register_extension_class4(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *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 GDExtensionClassCreationInfo5 *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 GDExtensionClassCreationInfo4 *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);
@ -427,17 +410,9 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr
}
if (self->reloadable && p_extension_funcs->recreate_instance_func == nullptr) {
bool can_create_class = (bool)p_extension_funcs->create_instance_func;
#ifndef DISABLE_DEPRECATED
if (!can_create_class && p_deprecated_funcs) {
can_create_class = (bool)p_deprecated_funcs->create_instance_func;
}
#endif
if (can_create_class) {
ERR_PRINT(vformat("Extension marked as reloadable, but attempted to register class '%s' which doesn't support reloading. Perhaps your language binding don't support it? Reloading disabled for this extension.", class_name));
self->reloadable = false;
}
}
extension->gdextension.library = self;
extension->gdextension.parent_class_name = parent_class_name;
@ -458,7 +433,6 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr
extension->gdextension.validate_property = p_extension_funcs->validate_property_func;
#ifndef DISABLE_DEPRECATED
if (p_deprecated_funcs) {
extension->gdextension.legacy_unexposed_class = p_deprecated_funcs->legacy_unexposed_class;
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;
@ -492,8 +466,6 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr
}
#endif
extension->gdextension.create_gdtype();
ClassDB::register_extension_class(&extension->gdextension);
if (p_extension_funcs->icon_path != nullptr) {
@ -714,12 +686,7 @@ void GDExtension::_register_get_classes_used_callback(GDExtensionClassLibraryPtr
#endif
}
void GDExtension::_register_main_loop_callbacks(GDExtensionClassLibraryPtr p_library, const GDExtensionMainLoopCallbacks *p_callbacks) {
GDExtension *self = reinterpret_cast<GDExtension *>(p_library);
self->startup_callback = p_callbacks->startup_func;
self->shutdown_callback = p_callbacks->shutdown_func;
self->frame_callback = p_callbacks->frame_func;
}
HashMap<StringName, GDExtensionInterfaceFunctionPtr> GDExtension::gdextension_interface_functions;
void GDExtension::register_interface_function(const StringName &p_function_name, GDExtensionInterfaceFunctionPtr p_function_pointer) {
ERR_FAIL_COND_MSG(gdextension_interface_functions.has(p_function_name), vformat("Attempt to register interface function '%s', which appears to be already registered.", p_function_name));
@ -805,6 +772,9 @@ void GDExtension::_bind_methods() {
BIND_ENUM_CONSTANT(INITIALIZATION_LEVEL_EDITOR);
}
GDExtension::GDExtension() {
}
GDExtension::~GDExtension() {
if (is_library_open()) {
close_library();
@ -824,9 +794,8 @@ void GDExtension::initialize_gdextensions() {
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);
register_interface_function("classdb_register_extension_class4", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class4);
#endif // DISABLE_DEPRECATED
register_interface_function("classdb_register_extension_class5", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class5);
register_interface_function("classdb_register_extension_class4", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_extension_class4);
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);
@ -838,7 +807,6 @@ void GDExtension::initialize_gdextensions() {
register_interface_function("classdb_unregister_extension_class", (GDExtensionInterfaceFunctionPtr)&GDExtension::_unregister_extension_class);
register_interface_function("get_library_path", (GDExtensionInterfaceFunctionPtr)&GDExtension::_get_library_path);
register_interface_function("editor_register_get_classes_used_callback", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_get_classes_used_callback);
register_interface_function("register_main_loop_callbacks", (GDExtensionInterfaceFunctionPtr)&GDExtension::_register_main_loop_callbacks);
}
void GDExtension::finalize_gdextensions() {
@ -888,26 +856,14 @@ bool GDExtensionResourceLoader::handles_type(const String &p_type) const {
}
String GDExtensionResourceLoader::get_resource_type(const String &p_path) const {
if (p_path.has_extension("gdextension")) {
String el = p_path.get_extension().to_lower();
if (el == "gdextension") {
return "GDExtension";
}
return "";
}
#ifdef TOOLS_ENABLED
void GDExtensionResourceLoader::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) {
Ref<GDExtension> gdext = ResourceLoader::load(p_path);
if (gdext.is_null()) {
return;
}
for (const StringName class_name : gdext->get_classes_used()) {
if (ClassDB::class_exists(class_name)) {
r_classes->insert(class_name);
}
}
}
bool GDExtension::has_library_changed() const {
return loader->has_library_changed();
}
@ -951,7 +907,7 @@ void GDExtension::prepare_reload() {
state.push_back(Pair<String, Variant>(P.name, value));
}
E.value.instance_state[obj_id] = {
std::move(state), // List<Pair<String, Variant>> properties;
state, // List<Pair<String, Variant>> properties;
obj->is_extension_placeholder(), // bool is_placeholder;
};
}
@ -973,8 +929,6 @@ void GDExtension::_clear_extension(Extension *p_extension) {
obj->clear_internal_extension();
}
p_extension->gdextension.destroy_gdtype();
}
void GDExtension::track_instance_binding(Object *p_object) {
@ -1096,9 +1050,13 @@ PackedStringArray GDExtension::get_classes_used() const {
return ret;
}
Vector<StringName> GDExtensionEditorPlugins::extension_classes;
GDExtensionEditorPlugins::EditorPluginRegisterFunc GDExtensionEditorPlugins::editor_node_add_plugin = nullptr;
GDExtensionEditorPlugins::EditorPluginRegisterFunc GDExtensionEditorPlugins::editor_node_remove_plugin = nullptr;
void GDExtensionEditorPlugins::add_extension_class(const StringName &p_class_name) {
if (editor_node_add_plugin) {
callable_mp_static(editor_node_add_plugin).call_deferred(p_class_name);
editor_node_add_plugin(p_class_name);
} else {
extension_classes.push_back(p_class_name);
}
@ -1112,6 +1070,9 @@ void GDExtensionEditorPlugins::remove_extension_class(const StringName &p_class_
}
}
GDExtensionEditorHelp::EditorHelpLoadXmlBufferFunc GDExtensionEditorHelp::editor_help_load_xml_buffer = nullptr;
GDExtensionEditorHelp::EditorHelpRemoveClassFunc GDExtensionEditorHelp::editor_help_remove_class = nullptr;
void GDExtensionEditorHelp::load_xml_buffer(const uint8_t *p_buffer, int p_size) {
ERR_FAIL_NULL(editor_help_load_xml_buffer);
editor_help_load_xml_buffer(p_buffer, p_size);

View file

@ -30,8 +30,9 @@
#pragma once
#include "core/extension/gdextension_interface.gen.h"
#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"
@ -66,7 +67,6 @@ class GDExtension : public Resource {
struct ClassCreationDeprecatedInfo {
#ifndef DISABLE_DEPRECATED
bool legacy_unexposed_class = false;
GDExtensionClassNotification notification_func = nullptr;
GDExtensionClassFreePropertyList free_property_list_func = nullptr;
GDExtensionClassCreateInstance create_instance_func = nullptr;
@ -80,10 +80,9 @@ class GDExtension : public Resource {
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);
static void _register_extension_class4(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo4 *p_extension_funcs);
#endif // DISABLE_DEPRECATED
static void _register_extension_class5(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo5 *p_extension_funcs);
static void _register_extension_class_internal(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstStringNamePtr p_parent_class_name, const GDExtensionClassCreationInfo5 *p_extension_funcs, const ClassCreationDeprecatedInfo *p_deprecated_funcs = nullptr);
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_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);
@ -95,7 +94,6 @@ class GDExtension : public Resource {
static void _unregister_extension_class(GDExtensionClassLibraryPtr p_library, GDExtensionConstStringNamePtr p_class_name);
static void _get_library_path(GDExtensionClassLibraryPtr p_library, GDExtensionStringPtr r_path);
static void _register_get_classes_used_callback(GDExtensionClassLibraryPtr p_library, GDExtensionEditorGetClassesUsedCallback p_callback);
static void _register_main_loop_callbacks(GDExtensionClassLibraryPtr p_library, const GDExtensionMainLoopCallbacks *p_callbacks);
GDExtensionInitialization initialization;
int32_t level_initialized = -1;
@ -117,11 +115,7 @@ class GDExtension : public Resource {
void clear_instance_bindings();
#endif
GDExtensionMainLoopStartupCallback startup_callback = nullptr;
GDExtensionMainLoopShutdownCallback shutdown_callback = nullptr;
GDExtensionMainLoopFrameCallback frame_callback = nullptr;
static inline HashMap<StringName, GDExtensionInterfaceFunctionPtr> gdextension_interface_functions;
static HashMap<StringName, GDExtensionInterfaceFunctionPtr> gdextension_interface_functions;
protected:
static void _bind_methods();
@ -176,14 +170,13 @@ public:
static void initialize_gdextensions();
static void finalize_gdextensions();
GDExtension();
~GDExtension();
};
VARIANT_ENUM_CAST(GDExtension::InitializationLevel)
class GDExtensionResourceLoader : public ResourceFormatLoader {
GDSOFTCLASS(GDExtensionResourceLoader, ResourceFormatLoader);
public:
static Error load_gdextension_resource(const String &p_path, Ref<GDExtension> &p_extension);
@ -191,15 +184,12 @@ public:
virtual void get_recognized_extensions(List<String> *p_extensions) const override;
virtual bool handles_type(const String &p_type) const override;
virtual String get_resource_type(const String &p_path) const override;
#ifdef TOOLS_ENABLED
virtual void get_classes_used(const String &p_path, HashSet<StringName> *r_classes) override;
#endif // TOOLS_ENABLED
};
#ifdef TOOLS_ENABLED
class GDExtensionEditorPlugins {
private:
static inline Vector<StringName> extension_classes;
static Vector<StringName> extension_classes;
protected:
friend class EditorNode;
@ -207,8 +197,8 @@ protected:
// Since this in core, we can't directly reference EditorNode, so it will
// set these function pointers in its constructor.
typedef void (*EditorPluginRegisterFunc)(const StringName &p_class_name);
static inline EditorPluginRegisterFunc editor_node_add_plugin = nullptr;
static inline EditorPluginRegisterFunc editor_node_remove_plugin = nullptr;
static EditorPluginRegisterFunc editor_node_add_plugin;
static EditorPluginRegisterFunc editor_node_remove_plugin;
public:
static void add_extension_class(const StringName &p_class_name);
@ -228,10 +218,10 @@ protected:
// is initialized even _before_ it gets instantiated, as we need to rely on
// this method while initializing the engine.
typedef void (*EditorHelpLoadXmlBufferFunc)(const uint8_t *p_buffer, int p_size);
static inline EditorHelpLoadXmlBufferFunc editor_help_load_xml_buffer = nullptr;
static EditorHelpLoadXmlBufferFunc editor_help_load_xml_buffer;
typedef void (*EditorHelpRemoveClassFunc)(const String &p_class);
static inline EditorHelpRemoveClassFunc editor_help_remove_class = nullptr;
static EditorHelpRemoveClassFunc editor_help_remove_class;
public:
static void load_xml_buffer(const uint8_t *p_buffer, int p_size);

View file

@ -1,53 +0,0 @@
/**************************************************************************/
/* gdextension_function_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. */
/**************************************************************************/
#pragma once
#include "core/extension/gdextension_loader.h"
class GDExtension;
class GDExtensionFunctionLoader : public GDExtensionLoader {
friend class GDExtensionManager;
friend class GDExtension;
String library_path;
GDExtensionInitializationFunction initialization_function = nullptr;
public:
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;
virtual bool library_exists() const override;
void set_initialization_function(GDExtensionInitializationFunction p_initialization_function);
};

View file

@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "gdextension_interface.gen.h"
#include "gdextension_interface.h"
#include "core/config/engine.h"
#include "core/extension/gdextension.h"
@ -43,6 +43,8 @@
#include "core/variant/variant.h"
#include "core/version.h"
#include <string.h>
class CallableCustomExtension : public CallableCustom {
void *userdata;
void *token;
@ -261,7 +263,6 @@ static void gdextension_get_godot_version2(GDExtensionGodotVersion2 *r_godot_ver
}
// Memory Functions
#ifndef DISABLE_DEPRECATED
static void *gdextension_mem_alloc(size_t p_size) {
return memalloc(p_size);
}
@ -273,19 +274,6 @@ static void *gdextension_mem_realloc(void *p_mem, size_t p_size) {
static void gdextension_mem_free(void *p_mem) {
memfree(p_mem);
}
#endif
static void *gdextension_mem_alloc2(size_t p_size, GDExtensionBool p_prepad_align) {
return Memory::alloc_static(p_size, p_prepad_align);
}
static void *gdextension_mem_realloc2(void *p_mem, size_t p_size, GDExtensionBool p_prepad_align) {
return Memory::realloc_static(p_mem, p_size, p_prepad_align);
}
static void gdextension_mem_free2(void *p_mem, GDExtensionBool p_prepad_align) {
Memory::free_static(p_mem, p_prepad_align);
}
// Helper print functions.
static void gdextension_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify) {
@ -817,11 +805,13 @@ static GDExtensionPtrOperatorEvaluator gdextension_variant_get_ptr_operator_eval
}
static GDExtensionPtrBuiltInMethod gdextension_variant_get_ptr_builtin_method(GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_method, GDExtensionInt p_hash) {
const StringName method = *reinterpret_cast<const StringName *>(p_method);
GDExtensionPtrBuiltInMethod ptr = (GDExtensionPtrBuiltInMethod)Variant::get_ptr_builtin_method_with_compatibility(Variant::Type(p_type), method, p_hash);
if (!ptr) {
ERR_PRINT("Error getting method " + method + ", missing or hash mismatch.");
uint32_t hash = Variant::get_builtin_method_hash(Variant::Type(p_type), method);
if (hash != p_hash) {
ERR_PRINT_ONCE("Error getting method " + method + ", hash mismatch.");
return nullptr;
}
return ptr;
return (GDExtensionPtrBuiltInMethod)Variant::get_ptr_builtin_method(Variant::Type(p_type), method);
}
static GDExtensionPtrConstructor gdextension_variant_get_ptr_constructor(GDExtensionVariantType p_type, int32_t p_constructor) {
return (GDExtensionPtrConstructor)Variant::get_ptr_constructor(Variant::Type(p_type), p_constructor);
@ -914,9 +904,8 @@ static void gdextension_string_new_with_wide_chars(GDExtensionUninitializedStrin
}
static void gdextension_string_new_with_latin1_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
const size_t string_length = p_contents ? (p_size < 0 ? strlen(p_contents) : strnlen(p_contents, p_size)) : 0;
String *dest = memnew_placement(r_dest, String);
dest->append_latin1(Span(p_contents, string_length));
dest->append_latin1(Span(p_contents, p_contents ? _strlen_clipped(p_contents, p_size) : 0));
}
static void gdextension_string_new_with_utf8_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char *p_contents, GDExtensionInt p_size) {
@ -940,9 +929,8 @@ static GDExtensionInt gdextension_string_new_with_utf16_chars_and_len2(GDExtensi
}
static void gdextension_string_new_with_utf32_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const char32_t *p_contents, GDExtensionInt p_char_count) {
const size_t string_length = p_contents ? (p_char_count < 0 ? strlen(p_contents) : strnlen(p_contents, p_char_count)) : 0;
String *string = memnew_placement(r_dest, String);
string->append_utf32(Span(p_contents, string_length));
string->append_utf32(Span(p_contents, p_contents ? _strlen_clipped(p_contents, p_char_count) : 0));
}
static void gdextension_string_new_with_wide_chars_and_len(GDExtensionUninitializedStringPtr r_dest, const wchar_t *p_contents, GDExtensionInt p_char_count) {
@ -952,9 +940,8 @@ static void gdextension_string_new_with_wide_chars_and_len(GDExtensionUninitiali
dest->append_utf16((const char16_t *)p_contents, p_char_count);
} else {
// wchar_t is 32 bit (UTF-32).
const size_t string_length = p_contents ? (p_char_count < 0 ? strlen(p_contents) : strnlen((const char32_t *)p_contents, p_char_count)) : 0;
String *string = memnew_placement(r_dest, String);
string->append_utf32(Span((const char32_t *)p_contents, string_length));
string->append_utf32(Span((const char32_t *)p_contents, p_contents ? _strlen_clipped((const char32_t *)p_contents, p_char_count) : 0));
}
}
@ -1057,7 +1044,7 @@ static void gdextension_string_operator_plus_eq_c32str(GDExtensionStringPtr p_se
static GDExtensionInt gdextension_string_resize(GDExtensionStringPtr p_self, GDExtensionInt p_length) {
String *self = (String *)p_self;
return (*self).resize_uninitialized(p_length);
return (*self).resize(p_length);
}
static void gdextension_string_name_new_with_latin1_chars(GDExtensionUninitializedStringNamePtr r_dest, const char *p_contents, GDExtensionBool p_is_static) {
@ -1289,13 +1276,11 @@ static GDExtensionVariantPtr gdextension_array_operator_index_const(GDExtensionC
return (GDExtensionVariantPtr)&self->operator[](p_index);
}
#ifndef DISABLE_DEPRECATED
void gdextension_array_ref(GDExtensionTypePtr p_self, GDExtensionConstTypePtr p_from) {
Array *self = (Array *)p_self;
const Array *from = (const Array *)p_from;
self->Array::operator=(*from);
self->_ref(*from);
}
#endif // DISABLE_DEPRECATED
void gdextension_array_set_typed(GDExtensionTypePtr p_self, GDExtensionVariantType p_type, GDExtensionConstStringNamePtr p_class_name, GDExtensionConstVariantPtr p_script) {
Array *self = reinterpret_cast<Array *>(p_self);
@ -1699,14 +1684,9 @@ void gdextension_setup_interface() {
REGISTER_INTERFACE_FUNC(get_godot_version);
#endif // DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(get_godot_version2);
#ifndef DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(mem_alloc);
REGISTER_INTERFACE_FUNC(mem_realloc);
REGISTER_INTERFACE_FUNC(mem_free);
#endif // DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(mem_alloc2);
REGISTER_INTERFACE_FUNC(mem_realloc2);
REGISTER_INTERFACE_FUNC(mem_free2);
REGISTER_INTERFACE_FUNC(print_error);
REGISTER_INTERFACE_FUNC(print_error_with_message);
REGISTER_INTERFACE_FUNC(print_warning);
@ -1817,9 +1797,7 @@ void gdextension_setup_interface() {
REGISTER_INTERFACE_FUNC(packed_vector4_array_operator_index_const);
REGISTER_INTERFACE_FUNC(array_operator_index);
REGISTER_INTERFACE_FUNC(array_operator_index_const);
#ifndef DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(array_ref);
#endif // DISABLE_DEPRECATED
REGISTER_INTERFACE_FUNC(array_set_typed);
REGISTER_INTERFACE_FUNC(dictionary_operator_index);
REGISTER_INTERFACE_FUNC(dictionary_operator_index_const);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,325 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://godotengine.org/gdextension_interface.schema.json",
"title": "GDExtension Interface",
"type": "object",
"properties": {
"_copyright": {
"type": "array",
"items": {
"type": "string"
}
},
"format_version": {
"type": "number",
"const": 1
},
"$schema": {
"type": "string",
"const": "./gdextension_interface.schema.json"
},
"types": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"kind": {
"type": "string",
"enum": ["enum", "handle", "alias", "struct", "function"]
},
"description": {
"type": "array",
"items": {
"type": "string"
}
},
"deprecated": {
"type": "object",
"properties": {
"since": {
"type": "string",
"pattern": "4\\.[0-9]+"
},
"message": {
"type": "string",
"pattern": "\\.$"
},
"replace_with": {
"type": "string"
}
},
"required": ["since"],
"additionalProperties": false
}
},
"required": [
"name",
"kind"
],
"unevaluatedProperties": false,
"allOf": [
{
"if": {
"properties": {
"kind": { "const": "enum" }
}
},
"then": {
"properties": {
"is_bitfield": {
"type": "boolean"
},
"values": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"value": {
"type": "number"
},
"description": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [ "name", "value" ],
"additionalProperties": false
}
}
},
"required": ["name", "kind", "values"]
}
},
{
"if": {
"properties": {
"kind": { "const": "handle" }
}
},
"then": {
"properties": {
"parent": {
"type": "string"
},
"is_const": {
"type": "boolean"
},
"is_uninitialized": {
"type": "boolean"
}
}
}
},
{
"if": {
"properties": {
"kind": { "const": "alias" }
}
},
"then": {
"properties": {
"type": {
"type": "string"
}
},
"required": ["name", "kind", "type"]
}
},
{
"if": {
"properties": {
"kind": { "const": "struct" }
}
},
"then": {
"properties": {
"members": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"description": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["name", "type"],
"additionalProperties": false
}
}
},
"required": ["name", "kind", "members"]
}
},
{
"if": {
"properties": {
"kind": { "const": "function" }
}
},
"then": {
"properties": {
"return_value": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"description": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["type"],
"additionalProperties": false
},
"arguments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"name": {
"type": "string"
},
"description": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["type"],
"additionalProperties": false
}
}
},
"required": ["name", "kind", "arguments"]
}
}
]
}
},
"interface": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"return_value": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"description": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["type"],
"additionalProperties": false
},
"arguments": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"name": {
"type": "string"
},
"description": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["type"],
"additionalProperties": false
}
},
"description": {
"type": "array",
"items": {
"type": "string"
}
},
"since": {
"type": "string",
"pattern": "4\\.[0-9]+"
},
"deprecated": {
"type": "object",
"properties": {
"since": {
"type": "string",
"pattern": "4\\.[0-9]+"
},
"message": {
"type": "string",
"pattern": "\\.$"
},
"replace_with": {
"type": "string"
}
},
"required": ["since"],
"additionalProperties": false
},
"see": {
"type": "array",
"items": {
"type": "string"
}
},
"legacy_type_name": {
"type": "string"
}
},
"required": [
"name",
"arguments",
"description",
"since"
],
"additionalProperties": false
}
}
},
"required": [
"_copyright",
"$schema",
"format_version",
"types",
"interface"
],
"additionalProperties": false
}

View file

@ -1,320 +0,0 @@
/**************************************************************************/
/* gdextension_interface_header_generator.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. */
/**************************************************************************/
#ifdef TOOLS_ENABLED
#include "gdextension_interface_header_generator.h"
#include "core/io/json.h"
#include "gdextension_interface_dump.gen.h"
static const char *FILE_HEADER =
"/**************************************************************************/\n"
"/* gdextension_interface.h */\n";
static const char *INTRO =
"\n"
"#pragma once\n"
"\n"
"/* This is a C class header, you can copy it and use it directly in your own binders.\n"
" * Together with the `extension_api.json` file, you should be able to generate any binder.\n"
" */\n"
"\n"
"#ifndef __cplusplus\n"
"#include <stddef.h>\n"
"#include <stdint.h>\n"
"\n"
"typedef uint32_t char32_t;\n"
"typedef uint16_t char16_t;\n"
"#else\n"
"#include <cstddef>\n"
"#include <cstdint>\n"
"\n"
"extern \"C\" {\n"
"#endif\n"
"\n";
static const char *OUTRO =
"#ifdef __cplusplus\n"
"}\n"
"#endif\n";
void GDExtensionInterfaceHeaderGenerator::generate_gdextension_interface_header(const String &p_path) {
Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
ERR_FAIL_COND_MSG(fa.is_null(), vformat("Cannot open file '%s' for writing.", p_path));
Vector<uint8_t> bytes = GDExtensionInterfaceDump::load_gdextension_interface_file();
String json_string = String::utf8(Span<char>((char *)bytes.ptr(), bytes.size()));
Ref<JSON> json;
json.instantiate();
Error err = json->parse(json_string);
ERR_FAIL_COND(err);
Dictionary data = json->get_data();
ERR_FAIL_COND(data.is_empty());
fa->store_string(FILE_HEADER);
Array copyright = data["_copyright"];
for (const Variant &line : copyright) {
fa->store_line(line);
}
fa->store_string(INTRO);
Array types = data["types"];
for (Dictionary type_dict : types) {
if (type_dict.has("description")) {
write_doc(fa, type_dict["description"]);
}
String kind = type_dict["kind"];
if (kind == "handle") {
type_dict["type"] = type_dict.get("is_const", false) ? "const void*" : "void*";
write_simple_type(fa, type_dict);
} else if (kind == "alias") {
write_simple_type(fa, type_dict);
} else if (kind == "enum") {
write_enum_type(fa, type_dict);
} else if (kind == "function") {
write_function_type(fa, type_dict);
} else if (kind == "struct") {
write_struct_type(fa, type_dict);
}
}
Array interfaces = data["interface"];
for (const Variant &interface : interfaces) {
write_interface(fa, interface);
}
fa->store_string(OUTRO);
}
void GDExtensionInterfaceHeaderGenerator::write_doc(const Ref<FileAccess> &p_fa, const Array &p_doc, const String &p_indent) {
if (p_doc.size() == 1) {
p_fa->store_string(vformat("%s/* %s */\n", p_indent, p_doc[0]));
return;
}
bool first = true;
for (const Variant &line : p_doc) {
if (first) {
p_fa->store_string(p_indent + "/*");
first = false;
} else {
p_fa->store_string(p_indent + " *");
}
if (line == "") {
p_fa->store_string("\n");
} else {
p_fa->store_line(String(" ") + (String)line);
}
}
p_fa->store_string(p_indent + " */\n");
}
void GDExtensionInterfaceHeaderGenerator::write_simple_type(const Ref<FileAccess> &p_fa, const Dictionary &p_type) {
String type_and_name = format_type_and_name(p_type["type"], p_type["name"]);
p_fa->store_string(vformat("typedef %s;%s\n", type_and_name, make_deprecated_comment_for_type(p_type)));
}
void GDExtensionInterfaceHeaderGenerator::write_enum_type(const Ref<FileAccess> &p_fa, const Dictionary &p_enum) {
p_fa->store_string("typedef enum {\n");
Array values = p_enum["values"];
for (Dictionary value_dict : values) {
if (value_dict.has("description")) {
write_doc(p_fa, value_dict["description"], "\t");
}
p_fa->store_string(vformat("\t%s = %s,\n", value_dict["name"], (int)value_dict["value"]));
}
p_fa->store_string(vformat("} %s;%s\n\n", p_enum["name"], make_deprecated_comment_for_type(p_enum)));
}
void GDExtensionInterfaceHeaderGenerator::write_function_type(const Ref<FileAccess> &p_fa, const Dictionary &p_func) {
String args_text = p_func.has("arguments") ? make_args_text(p_func["arguments"]) : "";
String name_and_args = vformat("(*%s)(%s)", p_func["name"], args_text);
String return_type;
if (p_func.has("return_value")) {
Dictionary ret = p_func["return_value"];
return_type = ret["type"];
} else {
return_type = "void";
}
p_fa->store_string(vformat("typedef %s;%s\n", format_type_and_name(return_type, name_and_args), make_deprecated_comment_for_type(p_func)));
}
void GDExtensionInterfaceHeaderGenerator::write_struct_type(const Ref<FileAccess> &p_fa, const Dictionary &p_struct) {
p_fa->store_string("typedef struct {\n");
Array members = p_struct["members"];
for (Dictionary member_dict : members) {
if (member_dict.has("description")) {
write_doc(p_fa, member_dict["description"], "\t");
}
p_fa->store_string(vformat("\t%s;\n", format_type_and_name(member_dict["type"], member_dict["name"])));
}
p_fa->store_string(vformat("} %s;%s\n\n", p_struct["name"], make_deprecated_comment_for_type(p_struct)));
}
String GDExtensionInterfaceHeaderGenerator::format_type_and_name(const String &p_type, const String &p_name) {
String ret = p_type;
bool is_pointer = false;
if (ret.ends_with("*")) {
ret = ret.substr(0, ret.size() - 2) + " *";
is_pointer = true;
}
if (!p_name.is_empty()) {
if (is_pointer) {
ret = ret + p_name;
} else {
ret = ret + " " + p_name;
}
}
return ret;
}
String GDExtensionInterfaceHeaderGenerator::make_deprecated_message(const Dictionary &p_data) {
PackedStringArray parts;
parts.push_back(vformat("Deprecated in Godot %s.", p_data["since"]));
if (p_data.has("message")) {
parts.push_back(p_data["message"]);
}
if (p_data.has("replace_with")) {
parts.push_back(vformat("Use `%s` instead.", p_data["replace_with"]));
}
return String(" ").join(parts);
}
String GDExtensionInterfaceHeaderGenerator::make_deprecated_comment_for_type(const Dictionary &p_type) {
if (!p_type.has("deprecated")) {
return "";
}
return vformat(" /* %s */", make_deprecated_message(p_type["deprecated"]));
}
String GDExtensionInterfaceHeaderGenerator::make_args_text(const Array &p_args) {
Vector<String> combined;
for (Dictionary arg_dict : p_args) {
combined.push_back(format_type_and_name(arg_dict["type"], arg_dict.get("name", String())));
}
return String(", ").join(combined);
}
void GDExtensionInterfaceHeaderGenerator::write_interface(const Ref<FileAccess> &p_fa, const Dictionary &p_interface) {
Vector<String> doc;
doc.push_back(String("@name ") + (String)p_interface["name"]);
doc.push_back(String("@since ") + (String)p_interface["since"]);
if (p_interface.has("deprecated")) {
doc.push_back(String("@deprecated ") + make_deprecated_message(p_interface["deprecated"]));
}
Array orig_doc = p_interface["description"];
for (int i = 0; i < orig_doc.size(); i++) {
// Put an empty line before the 1st and 2nd lines.
if (i <= 1) {
doc.push_back("");
}
doc.push_back(orig_doc[i]);
}
if (p_interface.has("arguments")) {
Array args = p_interface["arguments"];
if (args.size() > 0) {
doc.push_back("");
for (Dictionary arg_dict : args) {
String arg_string = String("@param ") + (String)arg_dict["name"];
if (arg_dict.has("description")) {
Array arg_doc = arg_dict["description"];
for (const Variant &d : arg_doc) {
arg_string += String(" ") + (String)d;
}
}
doc.push_back(arg_string);
}
}
}
if (p_interface.has("return_value")) {
Dictionary ret = p_interface["return_value"];
String ret_string = String("@return");
if (ret.has("description")) {
Array arg_doc = ret["description"];
for (const Variant &d : arg_doc) {
ret_string += String(" ") + (String)d;
}
}
doc.push_back("");
doc.push_back(ret_string);
}
if (p_interface.has("see")) {
Array see_array = p_interface["see"];
if (see_array.size() > 0) {
doc.push_back("");
for (const Variant &see : see_array) {
doc.push_back(String("@see ") + (String)see);
}
}
}
p_fa->store_string("/**\n");
for (const String &d : doc) {
if (d == "") {
p_fa->store_string(" *\n");
} else {
p_fa->store_string(vformat(" * %s\n", d));
}
}
p_fa->store_string(" */\n");
Dictionary func = p_interface.duplicate();
func.erase("deprecated");
if (p_interface.has("legacy_type_name")) {
// @todo When we can break compat, remove this! This maintains legacy type-o's in some type names.
func["name"] = p_interface["legacy_type_name"];
} else {
// Cannot use `to_pascal_case()` because it'll capitalize after numbers.
Vector<String> words = ((String)p_interface["name"]).split("_");
for (String &word : words) {
// Cannot use `capitalize()` on the whole string, because it'll separate numbers with a space.
word[0] = String::char_uppercase(word[0]);
}
func["name"] = String("GDExtensionInterface") + String().join(words);
}
write_function_type(p_fa, func);
p_fa->store_string("\n");
}
#endif // TOOLS_ENABLED

View file

@ -1,56 +0,0 @@
/**************************************************************************/
/* gdextension_interface_header_generator.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. */
/**************************************************************************/
#pragma once
#ifdef TOOLS_ENABLED
#include "core/io/file_access.h"
class GDExtensionInterfaceHeaderGenerator {
public:
static void generate_gdextension_interface_header(const String &p_path);
private:
static void write_doc(const Ref<FileAccess> &p_fa, const Array &p_doc, const String &p_indent = "");
static void write_simple_type(const Ref<FileAccess> &p_fa, const Dictionary &p_type);
static void write_enum_type(const Ref<FileAccess> &p_fa, const Dictionary &p_enum);
static void write_function_type(const Ref<FileAccess> &p_fa, const Dictionary &p_func);
static void write_struct_type(const Ref<FileAccess> &p_fa, const Dictionary &p_struct);
static String format_type_and_name(const String &p_type, const String &p_name);
static String make_deprecated_message(const Dictionary &p_data);
static String make_deprecated_comment_for_type(const Dictionary &p_type);
static String make_args_text(const Array &p_args);
static void write_interface(const Ref<FileAccess> &p_fa, const Dictionary &p_interface);
};
#endif // TOOLS_ENABLED

View file

@ -30,17 +30,16 @@
#include "gdextension_library_loader.h"
#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/io/dir_access.h"
#include "core/os/os.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")) {
Vector<String> config_dependencies = p_config->get_section_keys("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(".");
@ -74,7 +73,8 @@ Vector<SharedObject> GDExtensionLibraryLoader::find_extension_dependencies(const
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")) {
Vector<String> libraries = p_config->get_section_keys("libraries");
List<String> libraries;
p_config->get_section_keys("libraries", &libraries);
// Iterate the libraries, finding the best matching tags.
String best_library_path;
@ -197,14 +197,10 @@ Error GDExtensionLibraryLoader::open_library(const String &p_path) {
&abs_dependencies_paths, // library_dependencies
};
// Apple has a complex lookup system which goes beyond looking up the filename, so we try that first.
err = OS::get_singleton()->open_dynamic_library(abs_path, library, &data);
if (err != OK) {
err = OS::get_singleton()->open_dynamic_library(String(), library, &data);
err = OS::get_singleton()->open_dynamic_library(is_static_library ? String() : abs_path, library, &data);
if (err != OK) {
return err;
}
}
return OK;
}
@ -319,9 +315,7 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) {
compatible = GODOT_VERSION_PATCH >= compatibility_minimum[2];
}
if (!compatible) {
ERR_PRINT(vformat("GDExtension only compatible with Godot version %d.%d.%d or later: %s, but your Godot version is %d.%d.%d",
compatibility_minimum[0], compatibility_minimum[1], compatibility_minimum[2], p_path,
GODOT_VERSION_MAJOR, GODOT_VERSION_MINOR, GODOT_VERSION_PATCH));
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;
}
@ -353,8 +347,7 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) {
#endif
if (!compatible) {
ERR_PRINT(vformat("GDExtension only compatible with Godot version %s or earlier: %s, but your Godot version is %d.%d.%d",
compat_string, p_path, GODOT_VERSION_MAJOR, GODOT_VERSION_MINOR, GODOT_VERSION_PATCH));
ERR_PRINT(vformat("GDExtension only compatible with Godot version %s or earlier: %s", compat_string, p_path));
return ERR_INVALID_DATA;
}
}
@ -367,6 +360,8 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &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);
}
@ -383,7 +378,8 @@ Error GDExtensionLibraryLoader::parse_gdextension_file(const String &p_path) {
// Handle icons if any are specified.
if (config->has_section("icons")) {
Vector<String> keys = config->get_section_keys("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()) {

View file

@ -49,6 +49,8 @@ private:
String library_path;
String entry_symbol;
bool is_static_library = false;
#ifdef TOOLS_ENABLED
bool is_reloadable = false;
#endif

View file

@ -35,7 +35,7 @@
class GDExtension;
class GDExtensionLoader : public RefCounted {
GDSOFTCLASS(GDExtensionLoader, RefCounted);
GDSOFTCLASS(GDExtensionLoader, GDExtensionLoader);
public:
virtual Error open_library(const String &p_path) = 0;

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