initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
48
misc/utility/clang_format_glsl.yml
Normal file
48
misc/utility/clang_format_glsl.yml
Normal file
@@ -0,0 +1,48 @@
|
||||
# GLSL-specific rules.
|
||||
# The rules should be the same as .clang-format, except those explicitly mentioned.
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
AlignOperands: DontAlign
|
||||
AlignTrailingComments:
|
||||
Kind: Never
|
||||
OverEmptyLines: 0
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AttributeMacros:
|
||||
- _ALWAYS_INLINE_
|
||||
- _FORCE_INLINE_
|
||||
- _NO_INLINE_
|
||||
BreakConstructorInitializers: AfterColon
|
||||
ColumnLimit: 0
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
IncludeCategories:
|
||||
- Regex: ^".*"$
|
||||
Priority: 1
|
||||
- Regex: ^<.*\.h>$
|
||||
Priority: 2
|
||||
- Regex: ^<.*>$
|
||||
Priority: 3
|
||||
IndentCaseLabels: true
|
||||
IndentWidth: 4
|
||||
InsertBraces: true
|
||||
JavaImportGroups:
|
||||
- org.godotengine
|
||||
- android
|
||||
- androidx
|
||||
- com.android
|
||||
- com.google
|
||||
- java
|
||||
- javax
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
ObjCBlockIndentWidth: 4
|
||||
PackConstructorInitializers: NextLine
|
||||
RemoveSemicolon: false # Differs from base .clang-format
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 0
|
||||
Maximum: -1
|
||||
Standard: c++20
|
||||
TabWidth: 4
|
||||
UseTab: Always
|
152
misc/utility/color.py
Normal file
152
misc/utility/color.py
Normal file
@@ -0,0 +1,152 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from enum import Enum
|
||||
from typing import Final
|
||||
|
||||
# Colors are disabled in non-TTY environments such as pipes. This means if output is redirected
|
||||
# to a file, it won't contain color codes. Colors are enabled by default on continuous integration.
|
||||
|
||||
IS_CI: Final[bool] = bool(os.environ.get("CI"))
|
||||
NO_COLOR: Final[bool] = bool(os.environ.get("NO_COLOR"))
|
||||
CLICOLOR_FORCE: Final[bool] = bool(os.environ.get("CLICOLOR_FORCE"))
|
||||
STDOUT_TTY: Final[bool] = bool(sys.stdout.isatty())
|
||||
STDERR_TTY: Final[bool] = bool(sys.stderr.isatty())
|
||||
|
||||
|
||||
_STDOUT_ORIGINAL: Final[bool] = False if NO_COLOR else CLICOLOR_FORCE or IS_CI or STDOUT_TTY
|
||||
_STDERR_ORIGINAL: Final[bool] = False if NO_COLOR else CLICOLOR_FORCE or IS_CI or STDERR_TTY
|
||||
_stdout_override: bool = _STDOUT_ORIGINAL
|
||||
_stderr_override: bool = _STDERR_ORIGINAL
|
||||
|
||||
|
||||
def is_stdout_color() -> bool:
|
||||
return _stdout_override
|
||||
|
||||
|
||||
def is_stderr_color() -> bool:
|
||||
return _stderr_override
|
||||
|
||||
|
||||
def force_stdout_color(value: bool) -> None:
|
||||
"""
|
||||
Explicitly set `stdout` support for ANSI escape codes.
|
||||
If environment overrides exist, does nothing.
|
||||
"""
|
||||
if not NO_COLOR or not CLICOLOR_FORCE:
|
||||
global _stdout_override
|
||||
_stdout_override = value
|
||||
|
||||
|
||||
def force_stderr_color(value: bool) -> None:
|
||||
"""
|
||||
Explicitly set `stderr` support for ANSI escape codes.
|
||||
If environment overrides exist, does nothing.
|
||||
"""
|
||||
if not NO_COLOR or not CLICOLOR_FORCE:
|
||||
global _stderr_override
|
||||
_stderr_override = value
|
||||
|
||||
|
||||
class Ansi(Enum):
|
||||
"""
|
||||
Enum class for adding ANSI codepoints directly into strings. Automatically converts values to
|
||||
strings representing their internal value.
|
||||
"""
|
||||
|
||||
RESET = "\x1b[0m"
|
||||
|
||||
BOLD = "\x1b[1m"
|
||||
DIM = "\x1b[2m"
|
||||
ITALIC = "\x1b[3m"
|
||||
UNDERLINE = "\x1b[4m"
|
||||
STRIKETHROUGH = "\x1b[9m"
|
||||
REGULAR = "\x1b[22;23;24;29m"
|
||||
|
||||
BLACK = "\x1b[30m"
|
||||
RED = "\x1b[31m"
|
||||
GREEN = "\x1b[32m"
|
||||
YELLOW = "\x1b[33m"
|
||||
BLUE = "\x1b[34m"
|
||||
MAGENTA = "\x1b[35m"
|
||||
CYAN = "\x1b[36m"
|
||||
WHITE = "\x1b[37m"
|
||||
GRAY = "\x1b[90m"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.value
|
||||
|
||||
|
||||
RE_ANSI = re.compile(r"\x1b\[[=\?]?[;\d]+[a-zA-Z]")
|
||||
|
||||
|
||||
def color_print(*values: object, sep: str | None = " ", end: str | None = "\n", flush: bool = False) -> None:
|
||||
"""Prints a colored message to `stdout`. If disabled, ANSI codes are automatically stripped."""
|
||||
if is_stdout_color():
|
||||
print(*values, sep=sep, end=f"{Ansi.RESET}{end}", flush=flush)
|
||||
else:
|
||||
print(RE_ANSI.sub("", (sep or " ").join(map(str, values))), sep="", end=end, flush=flush)
|
||||
|
||||
|
||||
def color_printerr(*values: object, sep: str | None = " ", end: str | None = "\n", flush: bool = False) -> None:
|
||||
"""Prints a colored message to `stderr`. If disabled, ANSI codes are automatically stripped."""
|
||||
if is_stderr_color():
|
||||
print(*values, sep=sep, end=f"{Ansi.RESET}{end}", flush=flush, file=sys.stderr)
|
||||
else:
|
||||
print(RE_ANSI.sub("", (sep or " ").join(map(str, values))), sep="", end=end, flush=flush, file=sys.stderr)
|
||||
|
||||
|
||||
def print_info(*values: object) -> None:
|
||||
"""Prints a informational message with formatting."""
|
||||
color_print(f"{Ansi.GRAY}{Ansi.BOLD}INFO:{Ansi.REGULAR}", *values)
|
||||
|
||||
|
||||
def print_warning(*values: object) -> None:
|
||||
"""Prints a warning message with formatting."""
|
||||
color_printerr(f"{Ansi.YELLOW}{Ansi.BOLD}WARNING:{Ansi.REGULAR}", *values)
|
||||
|
||||
|
||||
def print_error(*values: object) -> None:
|
||||
"""Prints an error message with formatting."""
|
||||
color_printerr(f"{Ansi.RED}{Ansi.BOLD}ERROR:{Ansi.REGULAR}", *values)
|
||||
|
||||
|
||||
if sys.platform == "win32":
|
||||
|
||||
def _win_color_fix():
|
||||
"""Attempts to enable ANSI escape code support on Windows 10 and later."""
|
||||
from ctypes import POINTER, WINFUNCTYPE, WinError, windll
|
||||
from ctypes.wintypes import BOOL, DWORD, HANDLE
|
||||
|
||||
STDOUT_HANDLE = -11
|
||||
STDERR_HANDLE = -12
|
||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4
|
||||
|
||||
def err_handler(result, func, args):
|
||||
if not result:
|
||||
raise WinError()
|
||||
return args
|
||||
|
||||
GetStdHandle = WINFUNCTYPE(HANDLE, DWORD)(("GetStdHandle", windll.kernel32), ((1, "nStdHandle"),))
|
||||
GetConsoleMode = WINFUNCTYPE(BOOL, HANDLE, POINTER(DWORD))(
|
||||
("GetConsoleMode", windll.kernel32),
|
||||
((1, "hConsoleHandle"), (2, "lpMode")),
|
||||
)
|
||||
GetConsoleMode.errcheck = err_handler
|
||||
SetConsoleMode = WINFUNCTYPE(BOOL, HANDLE, DWORD)(
|
||||
("SetConsoleMode", windll.kernel32),
|
||||
((1, "hConsoleHandle"), (1, "dwMode")),
|
||||
)
|
||||
SetConsoleMode.errcheck = err_handler
|
||||
|
||||
for handle_id in [STDOUT_HANDLE, STDERR_HANDLE]:
|
||||
try:
|
||||
handle = GetStdHandle(handle_id)
|
||||
flags = GetConsoleMode(handle)
|
||||
SetConsoleMode(handle, flags | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
_win_color_fix()
|
119
misc/utility/godot_gdb_pretty_print.py
Normal file
119
misc/utility/godot_gdb_pretty_print.py
Normal file
@@ -0,0 +1,119 @@
|
||||
"""
|
||||
Load this file to your GDB session to enable pretty-printing of some Godot C++ types.
|
||||
|
||||
GDB command: `source misc/utility/godot_gdb_pretty_print.py`.
|
||||
|
||||
To load these automatically in Visual Studio Code, add the source command to
|
||||
the `setupCommands` of your configuration in `launch.json`:
|
||||
```json
|
||||
"setupCommands": [
|
||||
...
|
||||
{
|
||||
"description": "Load custom pretty-printers for Godot types.",
|
||||
"text": "source ${workspaceFolder}/misc/utility/godot_gdb_pretty_print.py"
|
||||
}
|
||||
]
|
||||
```
|
||||
Other UIs that use GDB under the hood are likely to have their own ways to achieve this.
|
||||
|
||||
To debug this script it's easiest to use the interactive python from a command-line
|
||||
GDB session. Stop at a breakpoint, then use python-interactive to enter the python shell
|
||||
and acquire a `Value` object using `gdb.selected_frame().read_var("variable name")`.
|
||||
From there you can figure out how to print it nicely.
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
import gdb # type: ignore
|
||||
import gdb.printing # type: ignore
|
||||
|
||||
|
||||
# Printer for Godot StringName variables.
|
||||
class GodotStringNamePrinter:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def to_string(self):
|
||||
return self.value["_data"]["name"]["_cowdata"]["_ptr"]
|
||||
|
||||
# Hint that the object is string-like.
|
||||
def display_hint(self):
|
||||
return "string"
|
||||
|
||||
|
||||
# Printer for Godot String variables.
|
||||
class GodotStringPrinter:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def to_string(self):
|
||||
return self.value["_cowdata"]["_ptr"]
|
||||
|
||||
# Hint that the object is string-like.
|
||||
def display_hint(self):
|
||||
return "string"
|
||||
|
||||
|
||||
# Printer for Godot Vector variables.
|
||||
class GodotVectorPrinter:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
# The COW (Copy On Write) object does a bunch of pointer arithmetic to access
|
||||
# its members.
|
||||
# The offsets are constants on the C++ side, optimized out, so not accessible to us.
|
||||
# I'll just hard code the observed values and hope they are the same forever.
|
||||
# See core/templates/cowdata.h
|
||||
SIZE_OFFSET = 8
|
||||
DATA_OFFSET = 16
|
||||
|
||||
# Figures out the number of elements in the vector.
|
||||
def get_size(self):
|
||||
cowdata = self.value["_cowdata"]
|
||||
if cowdata["_ptr"] == 0:
|
||||
return 0
|
||||
else:
|
||||
# The ptr member of cowdata does not point to the beginning of the
|
||||
# cowdata. It points to the beginning of the data section of the cowdata.
|
||||
# To get to the length section, we must back up to the beginning of the struct,
|
||||
# then move back forward to the size.
|
||||
# cf. CowData::_get_size
|
||||
ptr = cowdata["_ptr"].cast(gdb.lookup_type("uint8_t").pointer())
|
||||
return int((ptr - self.DATA_OFFSET + self.SIZE_OFFSET).dereference())
|
||||
|
||||
# Lists children of the value, in this case the vector's items.
|
||||
def children(self):
|
||||
# Return nothing if ptr is null.
|
||||
ptr = self.value["_cowdata"]["_ptr"]
|
||||
if ptr == 0:
|
||||
return
|
||||
# Yield the items one by one.
|
||||
for i in range(self.get_size()):
|
||||
yield str(i), (ptr + i).dereference()
|
||||
|
||||
def to_string(self):
|
||||
return "%s [%d]" % (self.value.type.name, self.get_size())
|
||||
|
||||
# Hint that the object is array-like.
|
||||
def display_hint(self):
|
||||
return "array"
|
||||
|
||||
|
||||
VECTOR_REGEX = re.compile("^Vector<.*$")
|
||||
|
||||
|
||||
# Tries to find a pretty printer for a debugger value.
|
||||
def lookup_pretty_printer(value):
|
||||
if value.type.name == "StringName":
|
||||
return GodotStringNamePrinter(value)
|
||||
if value.type.name == "String":
|
||||
return GodotStringPrinter(value)
|
||||
if value.type.name and VECTOR_REGEX.match(value.type.name):
|
||||
return GodotVectorPrinter(value)
|
||||
return None
|
||||
|
||||
|
||||
# Register our printer lookup function.
|
||||
# The first parameter could be used to limit the scope of the printer
|
||||
# to a specific object file, but that is unnecessary for us.
|
||||
gdb.printing.register_pretty_printer(None, lookup_pretty_printer)
|
32
misc/utility/problem-matchers.json
Normal file
32
misc/utility/problem-matchers.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "gcc",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(?:\\[[\\s\\d]{3}%\\]\\s)?(?:\\s|\\x1b\\[[=\\?]?[;\\d]+[a-zA-Z])*(?:\\d+\\>)?(\\S.*?)[:\\(](\\d+)(?:[,:](\\d+))?(?::{\\d+:\\d+\\-\\d+:\\d+})?\\)?:(?:\\s|\\x1b\\[[=\\?]?[;\\d]+[a-zA-Z])*(?:fatal\\s)?(error|warning)(?:\\s|\\x1b\\[[=\\?]?[;\\d]+[a-zA-Z])*:(?:\\s|\\x1b\\[[=\\?]?[;\\d]+[a-zA-Z])*(.*?)(?:\\[(.*)\\])?(?:\\s|\\x1b\\[[=\\?]?[;\\d]+[a-zA-Z])*$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"severity": 4,
|
||||
"message": 5,
|
||||
"code": 6
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "msvc",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(?:\\[[\\s\\d]{3}%\\]\\s)?(?:\\s|\\x1b\\[[=\\?]?[;\\d]+[a-zA-Z])*(?:\\d+\\>)?(\\S.*?)\\((\\d+)(?:,(\\d+))?(?:,\\d+,\\d+)?\\)(?:\\s|\\x1b\\[[=\\?]?[;\\d]+[a-zA-Z])*:(?:\\s|\\x1b\\[[=\\?]?[;\\d]+[a-zA-Z])*(?:fatal\\s)?(error|warning)(?:\\s|\\x1b\\[[=\\?]?[;\\d]+[a-zA-Z])*(\\w{1,2}\\d+):(?:\\s|\\x1b\\[[=\\?]?[;\\d]+[a-zA-Z])*(.*?)(?:\\s|\\x1b\\[[=\\?]?[;\\d]+[a-zA-Z])*$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"severity": 4,
|
||||
"code": 5,
|
||||
"message": 6
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
98
misc/utility/scons_hints.py
Normal file
98
misc/utility/scons_hints.py
Normal file
@@ -0,0 +1,98 @@
|
||||
"""
|
||||
Adds type hints to SCons scripts. Implemented via
|
||||
`from misc.utility.scons_hints import *`.
|
||||
|
||||
This is NOT a 1-1 representation of what the defines will represent in an
|
||||
SCons build, as proxies are almost always utilized instead. Rather, this is
|
||||
a means of tracing back what those proxies are calling to in the first place.
|
||||
"""
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
# ruff: noqa: F401
|
||||
from SCons.Action import Action
|
||||
from SCons.Builder import Builder
|
||||
from SCons.Defaults import Chmod, Copy, CScan, DefaultEnvironment, Delete, DirScanner, Mkdir, Move, Touch
|
||||
from SCons.Environment import Base
|
||||
from SCons.Platform import Platform
|
||||
from SCons.Platform.virtualenv import Virtualenv
|
||||
from SCons.Scanner import FindPathDirs, ScannerBase
|
||||
from SCons.Script import ARGLIST, ARGUMENTS, BUILD_TARGETS, COMMAND_LINE_TARGETS, DEFAULT_TARGETS
|
||||
from SCons.Script.Main import (
|
||||
AddOption,
|
||||
BuildTask,
|
||||
CleanTask,
|
||||
DebugOptions,
|
||||
GetBuildFailures,
|
||||
GetOption,
|
||||
PrintHelp,
|
||||
Progress,
|
||||
QuestionTask,
|
||||
SetOption,
|
||||
ValidateOptions,
|
||||
)
|
||||
from SCons.Script.SConscript import Configure, Return, SConsEnvironment, call_stack
|
||||
from SCons.Script.SConscript import SConsEnvironment as Environment
|
||||
from SCons.Subst import SetAllowableExceptions as AllowSubstExceptions
|
||||
from SCons.Tool import CScanner, DScanner, ProgramScanner, SourceFileScanner, Tool
|
||||
from SCons.Util import AddMethod, WhereIs
|
||||
from SCons.Variables import BoolVariable, EnumVariable, ListVariable, PackageVariable, PathVariable, Variables
|
||||
|
||||
# Global functions
|
||||
GetSConsVersion = SConsEnvironment.GetSConsVersion
|
||||
EnsurePythonVersion = SConsEnvironment.EnsurePythonVersion
|
||||
EnsureSConsVersion = SConsEnvironment.EnsureSConsVersion
|
||||
Exit = SConsEnvironment.Exit
|
||||
GetLaunchDir = SConsEnvironment.GetLaunchDir
|
||||
SConscriptChdir = SConsEnvironment.SConscriptChdir
|
||||
|
||||
# SConsEnvironment functions
|
||||
Default = SConsEnvironment(DefaultEnvironment()).Default
|
||||
Export = SConsEnvironment(DefaultEnvironment()).Export
|
||||
Help = SConsEnvironment(DefaultEnvironment()).Help
|
||||
Import = SConsEnvironment(DefaultEnvironment()).Import
|
||||
SConscript = SConsEnvironment(DefaultEnvironment()).SConscript
|
||||
|
||||
# Environment functions
|
||||
AddPostAction = DefaultEnvironment().AddPostAction
|
||||
AddPreAction = DefaultEnvironment().AddPreAction
|
||||
Alias = DefaultEnvironment().Alias
|
||||
AlwaysBuild = DefaultEnvironment().AlwaysBuild
|
||||
CacheDir = DefaultEnvironment().CacheDir
|
||||
Clean = DefaultEnvironment().Clean
|
||||
Command = DefaultEnvironment().Command
|
||||
Decider = DefaultEnvironment().Decider
|
||||
Depends = DefaultEnvironment().Depends
|
||||
Dir = DefaultEnvironment().Dir
|
||||
Entry = DefaultEnvironment().Entry
|
||||
Execute = DefaultEnvironment().Execute
|
||||
File = DefaultEnvironment().File
|
||||
FindFile = DefaultEnvironment().FindFile
|
||||
FindInstalledFiles = DefaultEnvironment().FindInstalledFiles
|
||||
FindSourceFiles = DefaultEnvironment().FindSourceFiles
|
||||
Flatten = DefaultEnvironment().Flatten
|
||||
GetBuildPath = DefaultEnvironment().GetBuildPath
|
||||
Glob = DefaultEnvironment().Glob
|
||||
Ignore = DefaultEnvironment().Ignore
|
||||
Install = DefaultEnvironment().Install
|
||||
InstallAs = DefaultEnvironment().InstallAs
|
||||
InstallVersionedLib = DefaultEnvironment().InstallVersionedLib
|
||||
Literal = DefaultEnvironment().Literal
|
||||
Local = DefaultEnvironment().Local
|
||||
NoCache = DefaultEnvironment().NoCache
|
||||
NoClean = DefaultEnvironment().NoClean
|
||||
ParseDepends = DefaultEnvironment().ParseDepends
|
||||
Precious = DefaultEnvironment().Precious
|
||||
PyPackageDir = DefaultEnvironment().PyPackageDir
|
||||
Repository = DefaultEnvironment().Repository
|
||||
Requires = DefaultEnvironment().Requires
|
||||
SConsignFile = DefaultEnvironment().SConsignFile
|
||||
SideEffect = DefaultEnvironment().SideEffect
|
||||
Split = DefaultEnvironment().Split
|
||||
Tag = DefaultEnvironment().Tag
|
||||
Value = DefaultEnvironment().Value
|
||||
VariantDir = DefaultEnvironment().VariantDir
|
||||
|
||||
env: SConsEnvironment
|
||||
env_modules: SConsEnvironment
|
24
misc/utility/svgo.config.mjs
Normal file
24
misc/utility/svgo.config.mjs
Normal file
@@ -0,0 +1,24 @@
|
||||
export default {
|
||||
multipass: true,
|
||||
precision: 2,
|
||||
js2svg: {
|
||||
eol: "lf",
|
||||
finalNewline: true,
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
name: "preset-default",
|
||||
params: {
|
||||
overrides: {
|
||||
removeHiddenElems: false,
|
||||
convertPathData: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
"convertStyleToAttrs",
|
||||
"removeScriptElement",
|
||||
"removeStyleElement",
|
||||
"reusePaths",
|
||||
"sortAttrs",
|
||||
],
|
||||
};
|
Reference in New Issue
Block a user